有没有一种方法可以在Crystal中使用_index进行分组



所以我有这个(排序很好的(数组。

有时我需要数组中的所有元素。但其他时候,我需要所有偶数索引的成员在一起,所有奇数索引的成员也在一起。再说一遍,有时我需要把它分成三组,一组的指数为0,3,6等,然后是1,4,7,最后是2,5,8。

这可以用group_by和取指数的模数来完成。亲眼目睹:

https://play.crystal-lang.org/#/r/4kzj

arr = ['a', 'b', 'c', 'd', 'e']
puts arr.group_by { |x| arr.index(x).not_nil! % 1 } # {0 => ['a', 'b', 'c', 'd', 'e']}
puts arr.group_by { |x| arr.index(x).not_nil! % 2 } # {0 => ['a', 'c', 'e'], 1 => ['b', 'd']}
puts arr.group_by { |x| arr.index(x).not_nil! % 3 } # {0 => ['a', 'd'], 1 => ['b', 'e'], 2 => ['c']}

但里面的not_nil!感觉像是一种代码气味/警告,有更好的方法。

我可以在不需要查找和处理Nil类型的情况下获得元素的索引吗?

您也可以只做:

arr = ['a', 'b', 'c', 'd', 'e']
i = 0
puts arr.group_by { |x| i += 1; i % 1 }
i = 0
puts arr.group_by { |x| i += 1; i % 2 }
i = 0
puts arr.group_by { |x| i += 1; i % 3 }

除了nillable返回类型之外,为每个元素调用Array#index也是非常低效的。这意味着O(N²(的运行时间。

#group_by用于按值分组,但您不需要该值进行分组,因为您只想按索引分组。这比包裹#group_by#index要容易得多

一个更有效的解决方案是在索引上循环,并根据索引对值进行分组:

groups = [[] of Char, [] of Char]
arr.each_index do |i|
groups[i % 2] << arr[i]
end

对此没有特殊的方法,但您自己实现它相当简单。

如果您不需要所有的组,而只需要其中一个组,那么还可以使用Int32#step每隔一个索引迭代一次:

group = [] of Char
2.step(to: arr.size - 1, by: 3) do |i|
group << arr[i]
end

相关内容

  • 没有找到相关文章

最新更新