如何拆分一个数组?

5

给定一个数组:

arr = [['a', '1'], ['b','2'], ['c', '3']] 

最好的方法是将其分成两个数组。

例如,从上面的数组中,我想得到以下两个数组:

first = ['a','b','c']  
second = ['1', '2', '3'] 

我可以使用collect吗?

1
这里很适合使用Array.unzip。不幸的是,目前没有一个.. - mykhal
4个回答

15

好的,我刚刚偶然发现了arr.transpose

arr = [['a', '1'], ['b','2'], ['c', '3']].transpose 

first = arr[0] 

second = arr[1] 

与上面的答案相比,arr.ziparr.mapforeach哪个更有效率?或者哪一个是最优雅的解决方案?

OR (感谢Jörg W Mittag的评论-请参见下面的评论) arr.transpose 可以分别赋值给first和second。


转置在我看来是最优雅的解决方案(但我是一名数学家)。我不确定哪种方法最有效,但我敢打赌zip,transpose和foreach几乎相同,而map稍微慢一些。如果您不想要每行中的所有元素(例如三个元素中的两个),foreach将具有优势。 - You
2
这基本上就是转置的全部意义,因此几乎可以保证它是最有效的。其他方法有稍微更多的移动部件,通常会导致效率略低。我怀疑差异通常不会太大。然而,转置方法肯定是最易读的,所以在我的书中,这将是它最大的优点。(我总是不愿意说一个方法是最有效的,期间,因为不同版本的Ruby中的性能问题通常会让我成为骗子。) - Chuck
11
你可以使用解构绑定:first, second = arr.transpose。这样会更加优雅。而且,既然我们在谈论性能方面:JRuby团队正在开发一种极度优化的编译器,可以在使用解构绑定、多赋值、多返回值、展开参数等时消除中间数组。(事实上,这个编译器非常出色,它的作者已要求他们将JRUBY的某些Java部分重写为Ruby,因为这样做实际上会更快。) - Jörg W Mittag
@你 但是zip确实是为数学家准备的。https://en.wikipedia.org/wiki/Anamorphism :-) - Vortico

4
使用zip方法也非常优雅:
arr[0].zip *arr[1..-1]
first = arr[0]
second = arr[1]

1
这基本上就相当于执行 arr.transpose,不过。 - You

1
arr = [['a', '1'], ['b','2'], ['c', '3']]

a = []
b = []

arr.each{ |i| a << i[0]; b << i[1] }

嗯,我刚刚偶然发现了arr.transpose。arr = [['a', '1'], ['b','2'], ['c', '3']].transpose first = arr[0] second = arr[1]我在想哪个更有效率。 - Ray Dookie
1
我认为对于3个项目来说这不会有影响 :-) 尝试使用更大的项目和一些类似于您真实数据的数据进行一些时间测试。 - Nikolaus Gradwohl

0

你可以通过collect(map的别名)来实现这一点,但不能在单个操作中完成,因为map / collect始终返回单个数组。你可以这样做

first = arr.map { |element| element[0] }   
second = arr.map { |element| element[1] }

这种方法的缺点是需要两次迭代arr。然而,除非你处理大量元素或者这个操作需要运行很多次,否则通常不会成为问题。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接