返回基于散列键/值范围的子数组?

时间:2013-11-01 15:38:48

标签: ruby arrays

我有一个排序的元素数组:

array = ["A", "B", "C", "D", "E"]

我定义了一系列元素,其中“key”是起始元素,“value”是结束元素:

range_1 = {"C" => "D"}
range_2 = {"B" => "E"}

如何根据解析上面数组的范围编写返回子数组的代码?

result_1 = ["C", "D"]
result_2 = ["B", "C", "D", "E"]

3 个答案:

答案 0 :(得分:2)

result_1 = array[array.index(range_1.keys.first)..array.index(range_1.values.first)]
result_2 = array[array.index(range_2.keys.first)..array.index(range_2.values.first)]

答案 1 :(得分:2)

假设您的数组元素是唯一的:

array = ["A", "B", "C", "D", "E"]

range_1 = {"C" => "D"}
range_2 = {"B" => "E"}

def subarray(array, range)
  from, to = range.first
  idx_from = array.index(from)
  idx_to = array.index(to)
  array[idx_from..idx_to]
end

subarray(array, range_1) # => ["C", "D"]
subarray(array, range_2) # => ["B", "C", "D", "E"]

答案 2 :(得分:1)

你是如何做到这一点的气味:

  • 而不是使用类似的东西:

    range_1 = {"C" => "D"}
    range_2 = {"B" => "E"}
    

    我选择使用真实范围:

    range_1 = 'C' .. 'D'
    range_2 = 'B' .. 'E'
    

    然后我可以省去array,因为将范围转换为连续值数组非常容易。

    range_1.to_a # => ["C", "D"]
    range_2.to_a # => ["B", "C", "D", "E"]
    
    [*range_1] # => ["C", "D"]
    [*range_2] # => ["B", "C", "D", "E"]
    
  • 如果array中的值不是真的连续,如示例所示,那么我将使用索引值:

    array = ["A", "B", "C", "D", "E"]
    range_1 = 2 .. 3
    range_2 = 1 .. 4
    

    这使得检索值变得容易:

    array = ["A", "B", "C", "D", "E"]
    range_1 = 2 .. 3
    range_2 = 1 .. 4
    
    array[range_1] # => ["C", "D"]
    array[range_2] # => ["B", "C", "D", "E"]
    

如果你需要使用array的实际值作为索引的符号名称,那就变得更难了,类似于你现在正在做的事情,但如果你正在使用网络前端,那就不太了坏。用户的大脑和眼睛是一个很好的资产。

由于用例没有明确定义,我们无法真正推荐更好的解决方案。我怀疑这是一个你已经确定某个算法是最好的情况,现在你正试图让它工作,但是当你觉得房间的角落接近时,熵正在进入。这是一个基于a的分析很多年来看代码,而不是快速判断。


  

但是这样的东西不是[“A”,“B”,“C”,“D”] [“B”......“D”]。我进入'[]':无法将String转换为整数

其他需要考虑的是哈希就像数组一样,只有使用values_at才能更轻松地随机访问。

考虑一下:

array = %w[a b c d x y z]
hash = Hash[array.map.with_index{ |e, i| [e, i] }]
hash # => {"a"=>0, "b"=>1, "c"=>2, "d"=>3, "x"=>4, "y"=>5, "z"=>6}

散列不需要值的整数,它们可以是nils或booleans,我根据我的需要使用它们。我在这里使用它们可以更明显地发生了什么。最大的好处是哈希允许我们以任何顺序提取内容,只需指定该顺序是什么。如果它是一个范围或一组范围,我们仍然可以按照我们想要的顺序提取值。

这是一个使用单一范围的简单示例:

hash.values_at(*('a' .. 'd')) # => [0, 1, 2, 3]
hash.values_at(*('x' .. 'z')) # => [4, 5, 6]

这些是复合范围示例:

hash.values_at(*('a' .. 'c'), *('x' .. 'z')) # => [0, 1, 2, 4, 5, 6]
hash.values_at(*('x' .. 'z'), *('a' .. 'c')) # => [4, 5, 6, 0, 1, 2]

请注意,范围中的第二个是反转的,值会反映出来。

另请注意,范围正在分解为数组。数组可以来自任何地方,只要元素与散列中的键匹配,您将看到以与数组相同的顺序返回的值。