【问题标题】:How do you guarantee that Arrays have a minimum level of recursion?您如何保证数组具有最低级别的递归?
【发布时间】:2013-11-25 03:21:45
【问题描述】:

我有一些在代码前面生成的不同长度的数组,由有序对的子数组组成。如果存在不止一对,则输出为 Array of Arrays。如果只有一对,则输出为单个数组。

什么是转换输出的简单、一致的方法,使其始终处于一个递归级别,而无需编写过于狭窄的内容来测试确切的发生情况?现在我有:

output_array = [7, 5]
output_array = output_array.flatten.each_slice(2).to_a
=> [[7, 5]]

output_array = [[7, 5], [6, 2]]
output_array = output_array.flatten.each_slice(2).to_a
=> [[7, 5], [6, 2]]

【问题讨论】:

  • 你所拥有的:flatten.each_slice(2).to_a 我也会这样做。
  • 我要感谢负责提升我之前评论的人。不幸的是,我的建议是不正确的。应该是:output_array = (output_array.first.is_a? Array) ? output_array : [output_array]
  • 是吗?不过,我可以在这里保证output_array 是一个数组。
  • 是的,但问题是output_array的元素本身是不是数组。

标签: ruby arrays recursion


【解决方案1】:

不那么可爱但更快的是检查内部元素是否为数组,如果不是则将其插入空数组。

oa1.first.kind_of?(Array) ? oa1 : [oa1]

Mudasobwa 请原谅我使用您的出色解决方案进行比较。

require 'benchmark'

n = 10_000
oa1 = [5,7]
oa2 = [[5,7],[6,8]]
c1 = c2 = c3 = 0 
Benchmark.bm do |x| 
  x.report {
    n.times do
      c1 += oa1.flatten.each_slice(2).to_a.first.first \
         +  oa2.flatten.each_slice(2).to_a.first.first
    end 
  }
  x.report {
    n.times do
      c2 += Hash[*oa1.flatten].to_a.first.first \
         +  Hash[*oa2.flatten].to_a.first.first
    end 
  }
  x.report {
    n.times do
      c3 += (oa1.first.kind_of?(Array) ? oa1 : [oa1]).first.first \
      +  (oa2.first.kind_of?(Array) ? oa2 : [oa2]).first.first \
    end 
  }
end

puts "c1 = #{c1}, c2 = #{c2}, c3 = #{c3}"

给予

   user     system      total        real
   0.063000   0.000000   0.063000 (  0.071007)
   0.062000   0.000000   0.062000 (  0.056006)
   0.016000   0.000000   0.016000 (  0.008001)
   c1 = 100000, c2 = 100000, c3 = 100000

【讨论】:

    【解决方案2】:

    [编辑] 注意!此解决方案在重复键 ([1,3,1,4]) 上失败,感谢 Shawn Balesstracci

    请使用下面@peter 建议的解决方案


    只是出于好奇,按 2 切片总是会迫使我们考虑类似哈希的结构,不是吗?因此,您可以使用:

    Hash[*output_array.flatten].to_a
    

    这至少快两倍:

    require 'benchmark'
    
    n = 10_000
    oa1 = [5,7]
    oa2 = [[5,7],[6,8]]
    c1 = c2 = 0 
    Benchmark.bm do |x| 
      x.report {
        n.times do
          c1 += oa1.flatten.each_slice(2).to_a.first.first \
             +  oa2.flatten.each_slice(2).to_a.first.first
        end 
      }
      x.report {
        n.times do
          c2 += Hash[*oa1.flatten].to_a.first.first \
             +  Hash[*oa2.flatten].to_a.first.first
        end 
      }
    end
    
    puts "c1 = #{c1}, c2 = #{c2}"
    
    
    user     system      total        real
      0.100000   0.000000   0.100000 (  0.117027)
      0.060000   0.000000   0.060000 (  0.064323)
    c1 = 100000, c2 = 100000
    

    【讨论】:

    • 哇,这是一个不错的技巧!绝对保存这个以备后用。阅读起来很复杂,您似乎想将其隐藏以将 Array 扩展为 enforce_recursion(level,sub_el_length) 之类的某种方法
    • 对我来说,这绝对是更容易阅读。一步一步说:“展平,做散列,把它变成一个数组”,而 hash 这里是“我对元组感兴趣”的关键字。
    • 重复键不会给出预期结果,例如 [1,3,1,4]
    • @ShawnBalestracci 谢谢,我更新了答案,澄清它实际上是错误的; @peter 下面的解决方案似乎是当时最好的方法。
    猜你喜欢
    • 2021-11-30
    • 2020-12-28
    • 1970-01-01
    • 2021-10-20
    • 2014-02-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多