0

私はjson構造を持っています:

[["item1", 1, 0], ["item1", 1, 0], ["item1", 1, 0], ["item2", 1, 0], ["item2", 1, 0],["item3", 1, 0],["item4", 1, 0],["item5", 1, 0]..]]

現在、ループを介して手動で合計して、次の結果を取得しています

[["item1", 3, 0], ["item2", 2, 0], ["item4", 1, 0], ["item5", 1, 0]]

それを行う別の方法はありますか?Rubyで配列モジュールを見ましたが、これを行う別の方法があるかどうかはわかりません...

編集:これは私がやっていたことです:ここでは、2番目の項目のみを合計しています

    @object = []
    @stat = Hash.new

    @data.each do |d|     

       if @object.include?(d[0])
         @stat [d[0]] += d[2]
       else
         @object << d[0]
         @stat[ d[0] ] = d[2]
       end
   end

編集2:

ワンライナーソリューションの時間を計り、自分のものと比較しました

ワンライナー: 0.005 鉱山: 0.007

これは私が最後に使用したものです:

data.inject(Hash.new(0)) { |stat, item| 
    if item[0] =~ /[a-z][a-z][0-9][0-9][a-z]/ # extra stuff that I needed 
      item[0] = item[0][0..8]
      stat[item[0]] += item[2]
    end
    stat
  }

みんなありがとう、たくさんのことを学びました。

4

7 に答える 7

2

配列を生成するワンライナー (例のように):

result = array.inject(Hash.new(0)){|h,item|h[item.first]+=item[2];h}.to_a

結果を配列ではなくハッシュにしたい場合は、.to_a

于 2013-09-06T17:11:47.390 に答える
1

効率的かどうかはわかりませんが、コードが少ない

require 'matrix'#not a gem, stdlib
munge = Hash.new(Matrix.zero(1,2))
array = [
  ["item1", 3, 0],
  ["item1", 1, 0],
  ["item1", 1, 0],
  ["item2", 5, 0],
  ["item1", 1, 0],
  ["item4", 1, 0],
  ["item3", 1, 0],
  ["item4", 1, 0]
]
array.each do |(key,a,b)|
  munge[key] += Matrix[[a, b]]
end
# {
#   "item1"=>Matrix[[6, 0]],
#   "item2"=>Matrix[[5, 0]],
#   "item4"=>Matrix[[2, 0]],
#   "item3"=>Matrix[[1, 0]],
# }
#force back into array
munge.each_key { |key| munge[key] = munge[key].row(0).to_a }

少し編集すると、さまざまな数の「列」を処理できます

require 'matrix'
array = [
  ["item1", 3, 0, 3, 0],
  ["item1", 1, 0, 1, 0],
  ["item1", 1, 1, 1, 7],
  ["item2", 5, 0, 5, 0],
  ["item1", 1, 0, 1, 2],
  ["item4", 1, 0, 5, 8],
  ["item3", 1, 0, 1, 0],
  ["item4", 1, 0, 1, 0]
]
munge = Hash.new(Matrix.zero(1, array.first.size - 1))
array.each do |(key,*arr)|
  munge[key] += Matrix[arr]
end
#{
#  "item1"=>Matrix[[6, 1, 6, 9]],
#  "item2"=>Matrix[[5, 0, 5, 0]],
#  "item4"=>Matrix[[2, 0, 6, 8]],
#  "item3"=>Matrix[[1, 0, 1, 0]]
#}
于 2013-09-06T17:14:44.003 に答える
1

スペンサーの答えの完成ですが、#chunkここでは確かに正しい答えです。

質問を正しく解釈すると、位置 0 に共通の値を持つすべての配列の位置 1 と 2 を合計する必要があります。提供されたデータには均一な値がありますが、私のソリューションはそれを想定していません。最初にチャンクする必要がありますposition[0]

a=[["item1", 1, 0], ["item1", 1, 0], ["item1", 1, 0], ["item2", 1, 0], ["item2", 1, 0], ["item3", 1, 0], ["item4", 1, 0], ["item5", 1, 0]]

chunked = a.chunk { |k| k[0] }
# => [["item1", [["item1", 1, 0], ["item1", 1, 0], ["item1", 1, 0]]], ["item2", [["item2", 1, 0], ["item2", 1, 0]]], ["item3", [["item3", 1, 0]]], ["item4", [["item4", 1, 0]]], ["item5", [["item5", 1, 0]]]]

次に、各チャンクの値を合計できます。これは、各チャンクを取得し、転置して配列内の特定のインデックスにあるすべての値を取得し、inject を介して対象の配列を合計することで簡単に実行できます。

chunked.map {|k, v| t = v.transpose; [k, t[1].inject(:+), t[2].inject(:+)] }
# => [["item1", 3, 0], ["item2", 2, 0], ["item3", 1, 0], ["item4", 1, 0], ["item5", 1, 0]]

組み合わせると、これは次のように簡単になります。

a.chunk {|k| k[0] }.map do |k, v|
  t = v.transpose
  [k, t[1].inject(:+), t[2].inject(:+)]
end
于 2013-09-06T17:16:44.137 に答える
1

チャンクメソッドをチェックしてください。これで正確な答えは得られませんが、そこにたどり着くはずです:

a=[["item1", 1, 0], ["item1", 1, 0], ["item1", 1, 0], ["item2", 1, 0], ["item2", 1, 0], ["item3", 1, 0], ["item4", 1, 0], ["item5", 1, 0]]

a.chunk { |k| k }.each { |k, v| p [k[0], v.length] }

["item1", 3]
["item2", 2]
["item3", 1]
["item4", 1]
["item5", 1]
于 2013-09-06T16:47:48.057 に答える
1

This should do it.

result = array.uniq.each do |a|
  a[1] = array.count { |b| b[0] == a[0] }
end

You could also use the chunk method as mentioned above:

result = []
array.chunk { |k| k }.each { |k, v| result << [k[0], v.length, k[2]] }

It's up to you which you like better. I prefer the first.

于 2013-09-06T16:46:48.750 に答える
1

きれいではありませんが、現在の形式のデータで実行したい場合は、次を使用できますgroup_by

data.group_by(&:first).reduce([]) do |acc, (k, v)|
  acc + [[ k, v.map { |x| x[1] }.reduce(:+), v.map { |x| x[2] }.reduce(:+) ]]
end

しかし、Ruby はオブジェクト指向言語です。このように使用すると、最も輝きます:-)。そのため、データのモデル クラスを作成して、データの操作を読みやすくすることを検討することをお勧めします。必要に応じて、私が共同で作成した ' id ' (id、ego、superego など) と呼ばれる gem を使用して、Ruby ハッシュからモデルを簡単に作成できます。

require 'id'

class Item
  include Id::Model

  field :name
  field :x
  field :y

  def + other
    fail unless name == other.name
    Item.new(name: name, x: x + other.x, y: y + other.y)
  end

end

items = data.map { |(name, x, y)| Item.new(name: name, x: x, y: y) }

その後、上記のgroup_byコードはより読みやすくなり、その意図をより適切に表現し始めます。

items.group_by(&:name).values.map { |v| v.reduce(:+) }
于 2013-09-06T19:29:19.503 に答える