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.