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

3 回答 3

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)]
于 2013-11-01T15:41:56.843 回答
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"]
于 2013-11-01T15:42:55.490 回答
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作为索引的符号名称,这将变得更加困难,类似于您现在正在做的事情,但如果您使用的是 Web 前端,那还不错。用户的大脑和眼睛是一笔不错的资产。

因为用例没有很好地定义,我们不能真正推荐更好的解决方案。我怀疑在这种情况下,您已经确定某种算法是最好的,现在您正试图使其发挥作用,但是当您感觉到房间的角落正在逼近时,熵就开始了。这是基于 a 的分析多年查看代码,而不是快速判断。


但是像这样的东西不是 ["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}

哈希值不需要整数,它们可以是 nil 或布尔值,我根据自己的需要使用了任何一种。我在这里使用它们来使正在发生的事情更加明显。最大的胜利是哈希允许我们以任何顺序提取内容,只需指定该顺序是什么。如果它是一个范围或一组范围,我们仍然可以按我们想要的顺序提取值。

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

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]

请注意,在第二个范围内,范围是相反的,并且值反映了这一点。

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

于 2013-11-01T16:32:04.733 回答