在Ruby中合并和交织两个数组


106

我有以下代码:

a = ["Cat", "Dog", "Mouse"]
s = ["and", "&"]

我想将数组合并s为数组a,这将给我:

["Cat", "and", "Dog", "&", "Mouse"]

查看Ruby Array和Enumerable文档,我看不到能实现此目的的方法。

有没有一种方法可以在不迭代每个数组的情况下做到这一点?


a将始终具有3个元素,而s将始终具有2个元素?一些更多的例子将是有用的。
tokland 2011年

Answers:


171

您可以执行以下操作:

a.zip(s).flatten.compact

4
如果a元素超过3个怎么办?
Michael Kohl

116
[“ a”,“ b”] .concat([“ c”,“ d”])#=> [“ a”,“ b”,“ c”,“ d”]
Leo Romanovsky,2012年

30
@ Leo,@ chuck:如果您阅读示例,您将看到Chris想要插入元素,而不是它们串联。本质上,他希望[a, s].transpose除了两行不符合之外,#zip这是显而易见的解决方案。而且我不相信他的意思是他真的在乎是否需要a突变...我不认为他根本没有评论过突变与功能解决方案,他只是在描述模式。
DigitalRoss

15
+1是唯一真正阅读过笨蛋问题的人!> _ <
马特·弗莱彻

5
更重要的是,如果两个数组的长度不相等怎么办?特别是如果s是更长的那个?我认为我可以确定Chris给出的示例不是他正在使用的实际数据。考虑:[] .zip [1,2] => nil(要在此上调用#flatten很难)[3,4] .zip([1、3、5、7])=> [[3 ,1],[
4,3

32

这不会按照Chris要求的顺序给出结果数组,但是如果结果数组的顺序无关紧要,则可以使用a |= b。如果您不想mutate a,则可以编写a | b结果并将其分配给变量。

请参阅位于http://www.ruby-doc.org/core/classes/Array.html#M000275的Array类的集合联合文档。

该答案假定您不希望重复数组元素。如果要在最终数组中允许重复的元素,a += b则应采取措施。同样,如果您不想mutate a,请使用a + b并将结果分配给变量。

为了回应此页面上的某些评论,这两种解决方案将适用于任何大小的阵列。


这绝对是最好的。
ardavis 2011年

11
这给出了["Cat", "Dog", "Mouse", "and", "&"],这不是OP想要的。
安德鲁·格林

非常棒,安德鲁。我将更新我的回答,说我没有回答克里斯的问题。
Michael Stalker

29

如果您不想重复,为什么不只使用union运算符:

new_array = a | s

1
为被低估,简单,优雅的解决方案授予+1。
Giacomo1968

当然可以回答问题!问题是:“我想将数组s合并为数组a”
道格拉斯

好的解决方案-但这确实改变了结果的顺序。的结果s将在新数组的末尾。
Hendrik

1
但是,元素的顺序将不是OP想要的。
tokland

6
s.inject(a, :<<)

s   #=> ["and", "&"]
a   #=> ["Cat", "Dog", "Mouse", "and", "&"]

它没有给您所需的顺序,但这是通过追加两个数组来合并两个数组的一种好方法。


我喜欢它,又短又干净。:)
纳法阿·布特弗

6

这是一个允许交错插入多个不同大小的数组的解决方案(一般解决方案):

arr = [["Cat", "Dog", "Mouse", "boo", "zoo"],
 ["and", "&"],
 ["hello", "there", "you"]]

first, *rest = *arr; first.zip(*rest).flatten.compact
=> ["Cat", "and", "hello", "Dog", "&", "there", "Mouse", "you", "boo", "zoo"]

2
真好!一个限制是,第一个数组必须是最长的。
布莱恩·

@BrianLow很棒!
阿卜杜

5

它并不十分优雅,但是可以用于任何大小的数组:

>> a.map.with_index { |x, i| [x, i == a.size - 2 ? s.last : s.first] }.flatten[0..-2] 
#=> ["Cat", "and", "Dog", "&", "Mouse"]

+1处理奇怪的情况,我认为i = s.cycle; a.map { |x| [x, i.next] }.flatten[0..-2]同样有效。
亩太短了

我不确定OP是否要替换and&,所以我尽可能地接受了他,同时允许a任何长度。
Michael Kohl

3

即使第一个数组不是最长的并且可以接受任意数量的数组,一种更通用的解决方案又如何呢?

a = [
    ["and", "&"],
    ["Cat", "Dog", "Mouse"]
]

b = a.max_by(&:length)
a -= [b]
b.zip(*a).flatten.compact

 => ["Cat", "and", "Dog", "&", "Mouse"]

2

要处理两个as的大小不同的情况:

a.zip(s).flatten.compact | s
  • .compactnila大于时将删除s
  • | ssa小于时添加剩余的项目s

1

进行交织并确保哪一个是zip方法的最大数组的一种方法是用其中一个数组填充nil直到另一个数组大小为止。这样,您还可以保证哪个数组的哪个元素位于第一个位置:

preferred_arr = ["Cat", "Dog", "Mouse"]
other_arr = ["and","&","are","great","friends"]

preferred_arr << nil while preferred_arr.length < other_arr.length
preferred_arr.zip(other_arr).flatten.compact
#=> ["Cat", "and", "Dog", "&", "Mouse", "are", "great", "friends"]

1
更好一点:(preferred_arr.zip(other_arr).flatten | other_arr无需零填充)
Adam Fendley

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.