【问题标题】:Looping to find out which array has the same digits as original array in Ruby [closed]循环找出哪个数组与Ruby中的原始数组具有相同的数字[关闭]
【发布时间】:2019-05-05 07:00:36
【问题描述】:

给定一个“初始数组”(例如[1, 2, 13]),我如何实现一种循环遍历子数组数组的方法,所有子数组的大小都与初始数组相同(例如,arr = [[2, 13, 1], [13, 1, 1], [13, 2, 2]])并找出是否至少一个子数组与初始数组中的值具有相同的值,并且这些值中的每一个在两个数组中的计数都相同?

在上面的例子中[1, 2, 13][2, 13, 1]都有一个1,一个2和一个13,所以应该返回true。如果arr 的第一个元素改为[2, 1, 1],则应返回false,因为arr 的任何元素的元素计数都与初始数组中的元素计数相同。

【问题讨论】:

  • 你想找出数组中每个元素的所有排列吗?如果是,提示:permutation.
  • 您可以对两个列表进行排序,然后检查排序后的列表是否相等。
  • jeporcher,我相信您会批准我对您问题的编辑。您接受@Kache 的回答这一事实让我相信我对这个问题的理解是正确的。
  • 为避免标记,通常最好根据实际 Ruby 代码的输入和所需输出来表达您的问题。这里的歧义是如果您要比较的那些数组是生成的、派生的,还是作为输入给出的。在表达您的问题时,请尝试将其草拟为代码,例如 def find_permutations(match, *list) 和一些演示调用,尽管没有实现,但会让您的意图变得清晰。
  • @tadman 感谢您的意见。从现在开始会牢记这一点。

标签: arrays ruby loops


【解决方案1】:

假设所有数组都已经在内存中,最简单的做法是:

sorted_initial_arr = [1, 2, 3].sort
arr_list = [[2, 3, 1], [3, 1, 1], [3, 2, 2]]

arr_list.any? { |arr| arr.sort == sorted_initial_arr }

更多“概念上”:

# some function to do "unordered equality"
unordered_equality_to_inital_arr = ->(arr) { arr.sort == sorted_initial_arr }

# apply that function across the array of arrays
arr_list.any?(&unordered_equality_to_inital_arr)

unordered_equality_to_inital_arr 组件可以通过多种方式实现,例如正如您提到的,使用permutation,不同之处在于它们的执行方式。

【讨论】:

  • 非常感谢您的周到回复。比较排序后的数组,我得到了想要的结果。
【解决方案2】:
arr = [[2, 3, 1, 3], [3, 1, 1, 3], [3, 2, 2, 1]]
target = [1, 2, 3, 2].group_by(&:itself)
  #=> {1=>[1], 2=>[2, 2], 3=>[3]}

arr.any? { |a| a.group_by(&:itself) == target }
  #=> true

注意

arr.map { |a| a.group_by(&:itself) }
  #=> [{2=>[2], 3=>[3, 3], 1=>[1]},
  #    {3=>[3, 3], 1=>[1, 1]}, 
  #    {3=>[3], 2=>[2, 2], 1=>[1]}]
{1=>[1], 2=>[2, 2], 3=>[3]} == {3=>[3], 2=>[2, 2], 1=>[1]}
  #=> true

Enumerable#group_by 的使用是单次计算(对于arr 的每个元素),比排序更有效。在计算复杂度方面,group_by 几乎是 O(n)(“几乎”因为哈希查找几乎是 O(1)),而 Array#sort(快速排序)是 O(n log n),@ 987654330@ 是arr 元素的大小。

另一种方法是使用计数哈希

target = [1, 2, 3, 2].each_with_object(Hash.new(0)) { |n,h| h[n] += 1 }
  #=> {1=>1, 2=>2, 3=>1}
arr.any? { |a| a.each_with_object(Hash.new(0)) { |n,h| h[n] += 1 } == target }
  #=> true

这也是一个单通道操作。

以下可能会更快,因为arr 的每个元素与target 的比较一旦可以得出计数中不匹配的结论就会终止。例如,如果像以前一样,

target
  #=> {1=>1, 2=>2, 3=>1}

a = [1, 1, 2, 3]

只要检查了a 中的第二个1,就会得出没有匹配的结论。计算如下。

arr.any? do |a|
  t = target.dup
  a.each do |n|
    break false unless t.key?(n)
    t[n] > 1 ? (t[n] -= 1) : t.delete(n)
  end && t.empty?        
end
  #=> true

【讨论】:

  • 优秀!非常感谢您的周到和彻底的答复。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-12-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多