ruby以类似于键的方式存储和查找2D数组中的数据

时间:2013-09-15 11:22:07

标签: ruby

假设我有一个像这样的数组:

groups = [ 
    ["G1", ["A0640", "A0660", "A0647", "A0643", "A0604", "A0644"]], 
    ["G2", ["A1609","A1611","A1608","A1610"]], 
    ["G3", ["A0613", "A0619", "A0637", "A0636"]],
    ["G4", ["A0646", "A0610", "A0645"]],
    ["G5", ["A0616", "A0611", "A0638", "A0606", "A0602", "A0639", "A0626", "A0605"]]
]

我要做的是找到数组元素的键或x [0]:使用:

groups .detect{|x,y| y.detect{|o| o == "A0619"} }[0]

有没有更好的方法呢?

3 个答案:

答案 0 :(得分:1)

我想我们可以假设“更好”你的意思是“更快”?如果速度(而不是语法)是问题,那么您可以使用不同的建议解决方案轻松测量需要多长时间:

Benchmark.bm(8) do |x|
  x.report("detect:") do 
    1_000_000.times { groups.detect{|x,y| y.detect{|o| o == "A0619"} }[0] }
  end
  x.report("include:") do 
    1_000_000.times { groups.detect{|x,y| y.include? "A0619" }[0] }
  end
  x.report("rassoc:") do 
    1_000_000.times { groups.map(&:flatten).rassoc("A0613").first }
  end
  x.report("hashwc:") do
    1_000_000.times do 
      hash = Hash[groups.flat_map { |key, values| values.map { |value| [value, key] } }]
      hash['A0619'] 
    end
  end
  x.report("hash-x:") do
    1_000_000.times do 
      Hash[groups].detect{|_,v| v.include? "A0619" }.first
    end
  end
end

           user     system      total        real
detect:    6.480000   0.020000   6.500000 (  6.523376)
include:   2.650000   0.000000   2.650000 (  2.658573)
rassoc:    9.920000   0.150000  10.070000 ( 10.099147)
hashwc:   21.440000   0.040000  21.480000 ( 21.543540)
hash-x:    5.690000   0.010000   5.700000 (  5.725335)

通过密钥直接访问哈希值的方式比任何一种方法都要快,所以如果你可以将这个数组存储为哈希值,你应该去做它(但只有在它不需要转换数组时)每一次)。

答案 1 :(得分:0)

您可以使用Enumerable#include?代替Enumerable#detect

groups.detect{|x,y| y.include? "A0619" }[0]
# => "G3"

如果您需要多次执行此操作,最好创建一个哈希:

groups = [ 
    ["G1", ["A0640", "A0660", "A0647", "A0643", "A0604", "A0644"]], 
    ["G2", ["A1609","A1611","A1608","A1610"]], 
    ["G3", ["A0613", "A0619", "A0637", "A0636"]],
    ["G4", ["A0646", "A0610", "A0645"]],
    ["G5", ["A0616", "A0611", "A0638", "A0606", "A0602", "A0639", "A0626", "A0605"]]
]
hash = Hash[groups.flat_map { |key, values| values.map { |value| [value, key] } }]
hash['A0619']
# => "G3"

答案 2 :(得分:0)

这是怎么回事?

groups = [ 
    ["G1", ["A0640", "A0660", "A0647", "A0643", "A0604", "A0644"]], 
    ["G2", ["A1609","A1611","A1608","A1610"]], 
    ["G3", ["A0613", "A0619", "A0637", "A0636"]],
    ["G4", ["A0646", "A0610", "A0645"]],
    ["G5", ["A0616", "A0611", "A0638", "A0606", "A0602", "A0639", "A0626", "A0605"]]
]

Hash[groups].detect{|_,v| v.include? "A0619" }.first
# => "G3"

<强>更新

groups = [ 
    ["G1", ["A0640", "A0660", "A0647", "A0643", "A0604", "A0644"]], 
    ["G2", ["A1609","A1611","A1608","A1610"]], 
    ["G3", ["A0613", "A0619", "A0637", "A0636"]],
    ["G4", ["A0646", "A0610", "A0645"]],
    ["G5", ["A0616", "A0611", "A0638", "A0606", "A0602", "A0639", "A0626", "A0605"]]
]

groups[groups.index{|_,a| a.include? "A0619"}][0]
# => "G3"

<强>的BenchMark

require "benchmark"

groups = [ 
    ["G1", ["A0640", "A0660", "A0647", "A0643", "A0604", "A0644"]], 
    ["G2", ["A1609","A1611","A1608","A1610"]], 
    ["G3", ["A0613", "A0619", "A0637", "A0636"]],
    ["G4", ["A0646", "A0610", "A0645"]],
    ["G5", ["A0616", "A0611", "A0638", "A0606", "A0602", "A0639", "A0626", "A0605"]]
]

Benchmark.bm(8) do |x|
  x.report("falsetru:") do 
    1_000_000.times { groups.detect{|x,y| y.detect{|o| o == "A0619"} }[0] }
  end
  x.report("Arup1") do 
    1_000_000.times { groups[groups.index{|_,a| a.include? "A0619"}][0] }
  end
  x.report("Arup2") do
    1_000_000.times do 
      Hash[groups].detect{|_,v| v.include? "A0619" }.first
    end
  end
end

<强>输出

               user     system      total        real
falsetru:  8.860000   0.000000   8.860000 (  8.885295)
Arup1      2.780000   0.000000   2.780000 (  2.800791)
Arup2      7.800000   0.000000   7.800000 (  7.825369)