你这样做有异味:
-
而不是使用类似的东西:
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"]。我进入 '[]': can't convert String into Integer
需要考虑的其他一点是,哈希就像数组一样,只是它们允许使用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]
请注意,在第二个范围内,范围是相反的,并且值反映了这一点。
还要注意范围被分解为数组。数组可以来自任何地方,只要元素与哈希中的键匹配,您就会看到返回的值与数组的顺序相同。