Ruby에서 두 배열 병합 및 인터리브


106

다음 코드가 있습니다.

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

나 에게 줄 배열 s에 배열 을 병합하고 a싶습니다.

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

Ruby Array 및 Enumerable 문서를 살펴보면이 작업을 수행 할 방법이 보이지 않습니다.

각 배열을 반복하지 않고이 작업을 수행 할 수있는 방법이 있습니까?


a는 항상 3 개의 요소와 2 개의 요소를가집니다. 더 많은 예가 유용 할 것입니다.
tokland 2011 년

답변:


171

다음과 같이 할 수 있습니다.

a.zip(s).flatten.compact

4
a요소가 3 개 이상 이면 어떻게 됩니까?
Michael Kohl 2011 년

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

30
@Leo, @chuck : 예제를 읽으면 Chris가 요소를 연결 하는 것이 아니라 인터리브를 원한다는 것을 알 수 있습니다. 본질적으로 그는 두 행이 일치하지 않는 것을 제외하고 는 명백한 해결책으로 남길 원합니다 . 그리고 나는 그가 그가 돌연변이 여부 에 대해 정말로 관심이 있다는 것을 의미한다고 믿지 않습니다 ... 나는 그가 돌연변이 된 대 기능적 솔루션에 대해 전혀 언급하지 않았다고 생각합니다. 그는 단지 패턴을 설명하려고 한 것입니다. [a, s].transpose#zipa
DigitalRoss 2013

15
실제로 블럼 민의 질문을 읽은 유일한 사람은 +1! > _ <
Matt Fletcher

5
더 중요한 것은 두 배열의 길이가 같지 않으면 어떻게 될까요? 특히 s가 더 긴 경우? Chris가 제시 한 예가 그가 작업하는 실제 데이터가 아니라고 안전하게 가정 할 수 있다고 생각합니다. 고려 : [] .zip [1, 2] => nil (#flatten을 호출하는 데 어려움이있을 것입니다) [3,4] .zip ([1, 3, 5, 7]) => [[3 , 1], [4, 3]] (죄송합니다. 두 번째 배열의 마지막 몇 가지 요소는 신경 쓰지 않습니다)
hoff2

32

이것은 Chris가 요청한 순서대로 결과 배열을 제공하지 않지만 결과 배열의 순서가 중요하지 않으면 a |= b. mutate를 원하지 않는 경우 결과를 작성하고 변수에 할당 a할 수 있습니다 a | b.

http://www.ruby-doc.org/core/classes/Array.html#M000275 에서 Array 클래스에 대한 집합 통합 문서를 참조하십시오 .

이 답변은 중복 배열 요소를 원하지 않는다고 가정합니다. 최종 배열에서 중복 요소를 허용 a += b하려면 트릭을 수행해야합니다. 다시 말하지만, 당신이 돌연변이하지 않으려는 경우 a, 사용 a + b및 변수에 결과를 할당합니다.

이 페이지의 일부 의견에 대한 응답으로이 두 솔루션은 모든 크기의 배열에서 작동합니다.


이것은 확실히 최고인 것 같습니다.
ardavis 2011 년

11
이것은 ["Cat", "Dog", "Mouse", "and", "&"]OP가 원하는 것이 아닙니다.
Andrew Grimm 2011 년

훌륭 해요, 앤드류 Chris의 질문에 대답하지 않았다고 대답하도록 업데이트하겠습니다.
Michael Stalker 2011 년

29

중복을 원하지 않는 경우 통합 연산자를 사용하십시오 .

new_array = a | s

1
과소 평가되고 단순하며 우아한 솔루션에 +1을 수여합니다.
Giacomo1968

물론 그것은 질문에 대답합니다! 질문 : "배열 s를 배열 a로 병합하고 싶습니다"
Douglas

좋은 솔루션-그러나 이것은 결과의 순서를 변경합니다. 의 결과 s는 새 어레이의 끝에 있습니다.
Hendrik 2015 년

1
그러나 요소의 순서는 OP가 원했던 것과는 다릅니다.
tokland

6
s.inject(a, :<<)

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

요청한 순서를 제공하지는 않지만 하나에 추가하여 두 배열을 병합하는 좋은 방법입니다.


나는 짧고 깨끗합니다. :)
Nafaa Boutefer 2015 년

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
좋은! 한 가지 제한은 첫 번째 배열이 가장 길어야한다는 것입니다.
Brian Low

@BrianLow 대박!
Abdo

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]똑같이 유효하다고 생각합니다.
mu가 너무 짧

나는 확실히 영업 이익은 대체하고자하는 경우 아니었다 and&허용하면서 나는 문자 그대로 가능한 한 그를했다, 그래서 a어떤 길이.
Michael Kohl 2011 년

3

첫 번째 배열이 가장 길지 않고 여러 배열을 허용하더라도 작동하는보다 일반적인 솔루션은 어떻습니까?

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

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

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

2

a& 둘 다 s같은 크기가 아닌 상황을 처리하려면 다음 을 수행하십시오.

a.zip(s).flatten.compact | s
  • .compact다음 보다 클 nil때 제거 됩니다.as
  • | s다음 보다 작을 s때 남은 항목을 추가합니다.as

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합니다 (무기 호 되메우기 없음)
아담 Fendley

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

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

5
죄송합니다 ... 출력을 원하는 특정 순서를 알아 차리지 못했습니다. 도와 주셔서 죄송합니다. 다시는 발생하지 않습니다.
David Morrow
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.