2013-07-26 61 views
0

有沒有更好的方法來做到這一點? 我有散列值的兩個陣列,以及我想獲得散列的陣列,其中所述天重疊,與版本設置爲交叉點(即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次。

我確實在rassoc和assoc上看到了這個,,但看起來他們需要是數組內部的數組,我後來使用這些散列作爲散列。

有沒有更好的方法來做到這一點?我不斷提出其他想法,但是當我真正研究它們時,它們都會回到兩個嵌套迭代。

+0

你能解釋一下這個數據是什麼?每個哈希和每個數組都有明顯的模式,這意味着您可以(也可能應該)將它們轉換爲類。 – Substantial

+0

每個數組代表一個搜索詞(我們讓人們搜索最多兩個方面)的出現,並且每個散列是天對象搜索項目的一個發生屬於並可能會或可能不會被包括在每個幾個版本(標準和/或其他幾個選項),由版本布爾值表示。我不明白它是如何將它們作爲類(或者它們將放在軌道中的位置)。這只是搜索算法的一小部分。我試圖獲得兩個搜索條件相交的每一天的日期和版本。 – ctaymor

回答

1

你從哪裏得到的散列這兩個數組?如果您將搜索條件存儲在SQL數據庫中,則這似乎是您可以使用查詢執行的操作。

否則,你可能會考慮使用一組找到了日期的交集。

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)] 

當然,如果這個東西是走出來的Pos​​tgres或東西,然後你的方式嘗試在查詢中執行此操作更好。在這種情況下,我剛纔寫的所有內容對你來說都是無用的。 ;)

+0

數據重組運作良好。我沒有意識到你可以使用這些日子自己作爲散列鍵。 – ctaymor