0

これを行うより良い方法はありますか?ハッシュの配列が 2 つあり、日付が重複するハッシュの配列を取得したいと考えています。バージョンは共通部分 (つまり、version1_for_arr1 && version1_for_arr2) に設定されています。

arr1は

[{:day=>day1, :version1=>true, :version2=>false, :version3=>true},
 {:day=>day3, :version1=>false, :version2=>false, :version3=>true},
 {:day=>day4, :version1=>true, :version2=>false, :version3=>false},
 {:day=>day5, :version1=>true, :version2=>true, :version3=>true},
 {:day=>day10, :version1=>true, :version2=>true, :version3=>true},
 {:day=>day15, :version1=>true, :version2=>false, :version3=>false}]

arr2は

[{:day=>day1, :version1=>false, :version2=>false, :version3=>true},
 {:day=>day2, :version1=>false, :version2=>false, :version3=>true},
 {:day=>day4, :version1=>true, :version2=>true, :version3=>false},
 {:day=>day5, :version1=>false, :version2=>true, :version3=>true},
 {:day=>day15, :version1=>true, :version2=>false, :version3=>false}]

この場合、最終的な配列は次のようになります。

[{:day=>day1, :version1=>false, :version2=>false, :version3=>true},
 {:day=>day4, :version1=>true, :version2=>false, :version3=>false},
 {:day=>day5, :version1=>false, :version2=>true, :version3=>true},
 {:day=>day15, :version1=>true, :version2=>false, :version3=>false}]

これを行うと考えることができる唯一の方法は、ネストされた反復としてです。

days=[]
arr1.each do |d1|
  arr2.each do |d2|
    if d1[:day]==d2[:day]
      days<<Hash.new(:day=>d1, :version1=>(d1[:version1]&&d2[:version1], :version2=>(d1[:version2]&&d2[:version2], :version3=>(d1[:version3]&&d2[:version3])
    end
  end
end

ただし、スケーリングされて配列が非常に大きくなると、非常にコストがかかるようです。n^n回繰り返しています。

http://rosettacode.org/wiki/Loop_over_multiple_arrays_simultaneously#Ruby on rassoc と assoc を見ましたが、それらは配列内の配列である必要があるようで、後で結果のハッシュをハッシュとして使用します。

これを行うより良い方法はありますか?私は他のアイデアを思いつき続けていますが、実際にそれらを調べてみると、それらはすべて 2 つのネストされたイテレーションに戻ってきます。

4

1 に答える 1

1

これら 2 つのハッシュの配列はどこから取得していますか? 検索用語を SQL データベースに保存している場合、これはクエリを使用して実行できるように思えます。

それ以外の場合は、 Set を使用して日付の交差を見つけることを検討してください。

require 'set'

def daylist(arr)
  arr.map { |a| a[:day] }
end

set1 = Set.new(daylist(arr1))
set2 = Set.new(daylist(arr2))

days = set1.intersection(set2)

result = ....

私はあなたのデータをさらに調べているので、データを再構築できるかどうか疑問に思っているので、ここでやめておきます。ハッシュの配列の代わりに、配列のハッシュを作成すると、変換が簡単になると思います。

require 'set'

h1 = {
  day1: [ true, false, true ],
  day3: [ false, false, true ],
  day4: [ true, false, false ],
  day5: [ true, true, true ],
  day10: [ true, true, true ],
  day15: [ true, false, false ]
}

h2 = {
  day1: [ false, false, true ],
  day2: [ false, false, true ],
  day4: [ true, true, false ],
  day5: [ false, true, true ],
  day15: [ true, false, false ]
}

# Intersect them.
set1 = Set.new(h1.keys)
set2 = Set.new(h2.keys)
intersection = set1.intersection(set2)

# Compute the lval & rval arrays
anded = intersection.map do |day|
  h1[day].each_with_index.map { |x, i| x && h2[day][i] }
end

# Convert them back into a Hash like our originals
final = Hash[intersection.zip(anded)]

もちろん、これが Postgres などから出てきたものである場合は、クエリでこれを実行する方がはるかに優れています。その場合、私が今書いたものはすべてあなたにとって役に立たないでしょう. ;)

于 2013-07-27T06:49:14.860 に答える