Ruby'de iki diziyi birleştirme ve serpiştirme


106

Takip koduna sahibim:

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

sDiziyi abana verecek olan diziyi birleştirmek istiyorum :

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

Ruby Dizisine ve Numaralandırılabilir dokümanlara baktığımda, bunu başaracak böyle bir yöntem görmüyorum.

Her diziyi yinelemeden bunu yapmanın bir yolu var mı?


a her zaman 3 elemente sahip olacak ve s iki? daha fazla örnek faydalı olacaktır.
tokland

Yanıtlar:


171

Bunu şununla yapabilirsiniz:

a.zip(s).flatten.compact

4
Ya a3'ten fazla element varsa?
Michael Kohl

116
["a", "b"] .concat (["c", "d"]) # => ["a", "b", "c", "d"]
Leo Romanovsky

31
@Leo, @chuck: Örneği okursanız, Chris'in öğeleri birleştirmek değil, araya eklemek istediğini göreceksiniz . Esasen, iki sıranın uyumlu olmaması dışında , bariz çözüm olarak ayrılmasını istiyor . Ve mutasyona uğramış olup olmadığını gerçekten önemsediğini kastettiğine inanmıyorum ... Mutasyona uğramış veya işlevsel bir çözüm hakkında yorum yaptığını sanmıyorum, sadece kalıbı tanımlamaya çalışıyordu. [a, s].transpose#zipa
DigitalRoss

15
Blummin 'sorusunu gerçekten okuyan tek kişi olduğu için +1! > _ <
Matt Fletcher

5
Daha da önemlisi, iki dizi eşit olmayan uzunluklara sahipse ne olur? Özellikle de s daha uzunsa? Sanırım Chris'in verdiği örneğin üzerinde çalıştığı gerçek veri olmadığını rahatlıkla varsayabilirim. göz önünde bulundurun: [] .zip [1, 2] => nil (bunun için #flatten'ı aramakta zorlanacaksınız) [3,4] .zip ([1, 3, 5, 7]) => [3 , 1], [4, 3]] (oops, sanırım 2. dizideki son birkaç öğeyi
umursamıyoruz

32

Bu, Chris'in istediği sırada bir sonuç dizisi vermez, ancak ortaya çıkan dizinin sıralaması önemli değilse, sadece kullanabilirsiniz a |= b. Mutasyona uğramak istemiyorsanız , sonucu bir değişkene ayazabilir a | bve atayabilirsiniz.

Array sınıfı için set birleşim belgelerine http://www.ruby-doc.org/core/classes/Array.html#M000275 adresinde bakın .

Bu yanıt, yinelenen dizi öğeleri istemediğinizi varsayar. Son dizinizde yinelenen öğelere izin vermek istiyorsanız a += b, hile yapmalısınız. Yine, mutasyona uğramak istemiyorsanız , sonucu akullanın a + bve bir değişkene atayın.

Bu sayfadaki bazı yorumlara yanıt olarak, bu iki çözüm her boyuttaki dizilerle çalışacaktır.


Bu kesinlikle en iyisi gibi görünüyor.
ardavis

12
Bu ["Cat", "Dog", "Mouse", "and", "&"], OP'nin istediği şey değildir.
Andrew Grimm

Harika görüş, Andrew. Cevabımı, Chris'in sorusuna cevap vermediğimi söyleyecek şekilde güncelleyeceğim.
Michael Stalker

29

Yinelenmesini istemiyorsanız, neden sadece birleşim operatörünü kullanmıyorsunuz :

new_array = a | s

1
Küçük, basit ve şık bir çözüm için +1 vermek.
Giacomo1968

Tabii ki soruyu cevaplıyor! Soru şuydu: "s dizisini a dizisiyle birleştirmek istiyorum"
Douglas

İyi çözüm - ancak bu sonuçların sırasını değiştirir. Sonuçları syeni dizinin sonunda olacaktır.
Hendrik

2
Öğelerin sırası, OP'nin istediği şey olmayacak.
tokland

6
s.inject(a, :<<)

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

Size istediğiniz sırayı vermez, ancak iki diziyi birine ekleyerek birleştirmenin güzel bir yoludur.


Kısa ve temiz severim. :)
Nafaa Boutefer

6

Farklı boyutlarda birden çok dizinin serpiştirilmesine izin veren bir çözüm aşağıda verilmiştir (genel çözüm):

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
Güzel! Bir sınırlama, ilk dizi en uzun olmalıdır.
Brian Low

@BrianLow harika yakala!
Abdo

5

Tam olarak zarif değil, ancak her boyuttaki diziler için işe yarıyor:

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

Garip uç durumlarla başa çıkmak için +1, i = s.cycle; a.map { |x| [x, i.next] }.flatten[0..-2]yine de eşit derecede geçerli olacağını düşünüyorum .
mu çok kısa

OP'nin değişmek isteyip istemediğinden emin değildim andve &bu yüzden aherhangi bir uzunluğa izin verirken onu olabildiğince tam anlamıyla aldım .
Michael Kohl

3

İlk dizi en uzun olmasa ve herhangi bir sayıda diziyi kabul etse bile çalışan daha genel bir çözüme ne dersiniz?

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

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

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

2

Her iki durumun üstesinden gelmek için ave saynı boyutta değildir:

a.zip(s).flatten.compact | s
  • .compactkaldıracaktır nilzaman adaha büyüktürs
  • | sdaha küçük solduğunda kalan öğeleri ekleyecektiras

1

Araya eklemeyi yapmanın ve zip yöntemi için hangisinin en büyük dizi olduğunu garanti etmenin bir yolu, dizilerden birini nildiğer dizi boyutuna kadar doldurmaktır . Bu şekilde, hangi dizinin hangi öğesinin ilk konumda olacağını da garanti edersiniz:

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
Biraz daha iyi: preferred_arr.zip(other_arr).flatten | other_arr(sıfır dolgusu olmadan)
Adam Fendley

-2
arr = [0, 1]
arr + [2, 3, 4]

//outputs [0, 1, 2, 3, 4]

5
üzgünüm ... çıktının girmesini istediğiniz belirli sırayı fark etmedim. Yardım etmeye çalıştığınız için özür dileriz, bir daha olmayacak.
David Morrow
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.