2013-11-01 54 views
1

我有元素的排序后的数组:基于哈希键/值范围返回子数组?

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

我所限定的范围内的元素,其中“密钥”是启动元件,并且“值”为结束元素:

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

我如何编写代码来返回基于范围解析上面的数组的子数组?

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

如果你想表达的红宝石范围,你应该使用'(“C” ..“d”)'。即使是以'start'开头的'H',end:'D'也可以代表数据。 – meagar

+0

我刚刚开始使用Ruby,我喜欢Hash'=>'表示法。看来我也会喜欢范围表示法。 – flyer

+0

@flyer:如果你拥有的唯一工具是锤子,那么每个问题看起来就像一个被砸的拇指。 :) –

回答

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"] 
+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

有一种气味,你是如何做的:

  • 而是使用类似的:

    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作为象征性的FO名称中使用的实际值索引变得越来越难,类似于你现在正在做的事情,但是如果你正在使用网络前端,那就不错。用户的大脑和眼睛是很好的资产。

由于用例不明确,我们不能真正推荐更好的解决方案。我怀疑这是一个情况,你已经决定某种算法是最好的,现在你试图让它工作,但是当你感觉房间的角落关闭时,熵会被设置。这是一个基于很多年看代码,而不是一个简单的判断。


但像这样desn't [ “A”, “B”, “C”, “d”] [ “B” .. “d”]。我得到了“[]”:不能转换成字符串整数

别的东西要考虑的是哈希与数组类似,只是它们允许随机存取更方便地使用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} 

哈希不需要整数的价值观,他们可能是尼尔斯或布尔值,我根据我的需求已经使用了两种。我在这里使用它们来更明显地发生了什么。最大的收获是哈希值可以让我们以任何顺序提取内容,只需指定该顺序即可。如果它是一个范围或一组范围,我们仍然可以按照我们想要的顺序提取值。

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

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] 

。注意,在该范围内的第二被颠倒,并且值反映。

还要注意,范围被分解成阵列。数组可以来自任何地方,只要元素与哈希中的键匹配,就会看到以与数组相同的顺序返回的值。而不是与单个键/值的哈希

+0

感谢有用的提示。不幸的是,这不能被使用,因为我没有连续的数组元素,我需要通过字符串来定义'范围'。建议'[“A”,“B”,“C”] [1..2]'完美,但类似这样的不是'[“A”,“B”,“C”,“D”] [ “B” .. “d”]'。我得到'in'[]':无法将字符串转换为整数' – flyer

+0

正确,您不能使用alpha范围,因为'[]'只支持整数。您的示例数组需要反映您的实际情况;如果你在数组中没有连续的值,那么确保注意到这一点。有一些非常有趣的技巧可以在散列和数组切片中使用,而哈希切片并不关心数组中的东西是否有序。值将按照指定键的顺序检索。 –