2011-01-22 5 views
3

아주 확실하지 나는 문제가 완전히 형성,하지만 난 할 노력하고있어 기본적으로 이것이다 :모든 가능한 값 조합의 배열로 배열을 결합하는 단일 라이너 알고리즘?

# where the indices correspond to attributes fore example: 
# [type, status] 
x = %w(a b) 
y = %w(c d) 
combine(x, y) #=> [["a", "b"], ["a", "d"], ["c", "a"], ["c", "b"]] 

배열의 순서는 항상 동일하므로 각각의 역 같은 [b, a]을 등 , 결과에 포함되지 않습니다.

이 내용은 무엇이며이를 구현하는 효율적인 방법은 무엇입니까? combine(*arrays)

감사 :

이 희망 배열과 값의 수를 작동합니다 ...

나는 Array#permutation를 볼 수 있지만, 그게 아주 아니에요! 다음

(x | y).combination(x.length).to_a 생산 :

x = ["front_door", "open"] 
y = ["back_door", "closed"] 
(x | y).combination(x.length).to_a 
=> [["front_door", "open"], ["front_door", "back_door"], ["front_door", "closed"], ["open", "back_door"], ["open", "closed"], ["back_door", "closed"]] 

내가 찾고 실제 결과가 이것이다 업데이트

여기에 내가 무엇을 찾고 더 나은 예제 :

=> [["front_door", "open"], ["front_door", "closed"], ["back_door", "open"], ["back_door", "closed"]] 

또는 더 긴 배열 인 경우 :

x = ["house", "front_door", "open"] 
y = ["building", "back_door", "closed"] 
compute(x, y) 
=> ["house", "front_door", "open"], ["house", "back_door", "open"], ["house", "front_door", "closed"], ["house", "back_door", "closed"], ["building", "front_door", "open"], ["building", "back_door", "open"], ["building", "front_door", "closed"], ["building", "back_door", "closed"] 

아이디어가 있으십니까?

+0

내가 첫 번째 예제에서 추측을 [ "C", "A"] [ "C"를 찾아야한다 , "d"] – tokland

답변

5
 

x.zip(y).reduce(:product).map(&:flatten) 
 

그리고 대한 여러 배열 :

 

x.zip(y,z,w).reduce(:product).map(&:flatten) 
 
+0

'' "house", "building"]','[ "front_door", "back_door"]','[ "open", "closed"]'어떻게 배열을 구성했는지 같은 결과가 나옵니까? –

+1

@vlatropos [[ "house", "building"], [ "front_door", "back_door"], [ "open", "closed"]] reduce (: product) .map (& : flatten). 대답의 zip은 원래 표현을이 표현으로 변형합니다. – adamax

+0

awesome, thanks a ton! –

3
(x | y).combination(x.length).to_a 
+0

이것은 정말 멋지지만 제 질문이 맞지 않다고 생각합니다 ... 질문을 업데이트했습니다. –

0
def combine(*arrays) 
    head, *tail = arrays.transpose 
    head.product(*tail) 
end 

combine(x, y) 
combine(x, y, z, ...) 

사이드 노트 여담 :이 기능 언어 기능이있는에 대해 당신이 포인트를 얻을 수있는 시나리오 중 하나입니다 중요한 물건. OOP에서 객체의 메서드를 호출해야한다는 사실 때문에이 경우에는 의도적으로 머리/꼬리를 가져야합니다. 당신이 함수로 product이있을 때, 파이썬에서 예를 들어, 문제의이 종류가 없습니다 :

itertools.product(*zip(*arrays)) 
+0

'x.zip (y) .reduce (: product)'가 파이썬 예제와 똑같은 일을합니까? –

+0

@ 마크 토마스. zip + reduce는 추가 수준의 중첩을 생성합니다 (그 때문에 adamax의 솔루션은 이후에 평평 해집니다). 게다가 매우 비효율적 인 Array # 제품은 임의의 수의 인수를 지원합니다. 줄이거 나 주입하지 말고 왜 사용합니까? – tokland

+0

그러나 요점은 개념적으로 이러한 종류의 작업이 OOP 패러다임에 잘 들어 맞지 않는다는 것입니다. 이것을 전치 할 때도 보게됩니다. 파이썬에서는 단순히 "zip (* list_of_lists)"라고 쓰지만 Ruby에서는 Array # transpose를 만들어야 만합니다. 그렇지 않으면 위의 예와 같이 수동으로 머리/꼬리를 가져와야합니다 : head, * tail = array_of_arrays; 우편 번호 (* 꼬리), 그리고 머리가 없으면 조심해!). 개념적으로 zip 작업은 배열 그룹을 사용하며 배열 나머지 부분은 압축하지 않기 때문입니다. 이봐 요, 그건 호언 장담이 아니에요. 루비가 너무 좋아요. – tokland

관련 문제