【问题标题】:Dealing with hashes inside arrays处理数组内的哈希
【发布时间】:2013-07-26 22:58:14
【问题描述】:

有没有更好的方法来做到这一点? 我有两个哈希数组,我想得到一个哈希数组,其中日期重叠,版本设置为交集(即 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 上看到了 http://rosettacode.org/wiki/Loop_over_multiple_arrays_simultaneously#Ruby,但看起来它们需要是数组内部的数组,我稍后将生成的哈希用作哈希。

有没有更好的方法来做到这一点?我不断提出其他想法,但当我真正检查它们时,它们都会回到两个嵌套迭代。

【问题讨论】:

  • 你能解释一下这个数据是什么吗?每个散列和每个数组都有明显的模式,这意味着您可以(并且可能应该)将它们转换为类。
  • 每个数组代表一个搜索词的出现(我们让人们搜索最多两个词),每个哈希是该搜索词的出现属于的日期对象,可能是也可能不是包含在几个版本(标准和/或几个其他选项)中的每一个中,由版本布尔值表示。我不明白将它们作为类(或它们将在哪里去)将如何工作。这只是搜索算法的一小部分。我正在尝试获取两个搜索词相交的每一天的日期和版本。

标签: ruby-on-rails arrays hash iteration


【解决方案1】:

你从哪里得到这两个哈希数组?如果您将搜索词存储在 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 或其他东西,那么你最好尝试在查询中执行此操作。在那种情况下,我刚刚写的所有东西对你来说都是无用的。 ;)

【讨论】:

  • 数据的重组效果很好。我没有意识到您可以将日期本身用作哈希键。
猜你喜欢
  • 2014-03-30
  • 2014-01-04
  • 2021-02-05
  • 2014-03-29
  • 2016-06-27
  • 1970-01-01
  • 2015-06-04
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多