2013-07-26 111 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