2012-05-18 49 views
9

Tôi có hai danh sách sau đây:python: lạ yếu tố danh sách kết hợp

l1 = [1, 2, ,3] 
l2 = [x, y] 

Và muốn có tất cả các danh sách gồm 5 yếu tố giữ trật tự của chỉ l1. Nói:

[x, y, 1, 2, 3], 
[x, 1, y, 2, 3], 
[x, 1, 2, y, 3], 
[x, 1, 2, 3, y], 
[y, x, 1, 2, 3], 
[y, 1, x, 2, 3], 
[y, 1, 2, x, 3], 
[y, 1, 2, 3, x], 
[1, x, y, 2, 3], 
[1, x, 2, y, 3], 
[1, x, 2, 3, y], 
[1, y, x, 2, 3], 
[1, y, 2, x, 3], 
[1, y, 2, 3, x], 
... 
[1, 2, 3, y, x], 
... 
[1, 2, 3, x, y] 

Quan sát rằng thứ tự của l1 là quan trọng và l2 thì không. l2 yếu tố chạy trên vị trí l1 + l2 nhưng chỉ thứ tự của l1 là quan trọng. Tôi đang đấu tranh với điều này. Bất kỳ trợ giúp được đánh giá cao.

+7

@Marcin: Tôi thực sự không thích câu hỏi đó; tại sao mọi người sẽ hỏi một câu hỏi nếu họ không gặp khó khăn trong việc tìm ra nơi để bắt đầu? Có một số câu hỏi đáng khen là ("làm bài tập về nhà"), nhưng tôi không cảm thấy đây là một trong số đó. – ninjagecko

+3

Đây không phải là công việc nhà của tôi. Đây là một quá đơn giản hóa vấn đề của tôi. Tôi làm việc với sự sắp xếp chuỗi protein và gặp khó khăn. Không thể tìm ra cách tốt nhất để giải quyết vấn đề này. Dù sao cũng cảm ơn bạn. – fred

+0

@ninjagecko (a) Cho dù đó là bài tập về nhà, số tiền này "viết một số mã tổ hợp cho tôi miễn phí" (b) một số mã chiếu sáng cả mục tiêu và vấn đề cụ thể là gì. – Marcin

Trả lời

0

Tôi đã thử một thứ gì đó bằng cách sử dụng bộ giữ chỗ cho lớp học cho l1 và itertools.permutations nhưng đã có bản sao trong đó.

Vì vậy, cố gắng một lần nữa, đây là đơn giản nhất tôi đã có thể để có được nó:

from itertools import combinations, permutations 

l1 = [1, 2, 3] 
l2 = ["x", "y"] 
r = range(len(l1)+len(l2)) 
for combo in combinations(r,len(l2)): 
    for permu in permutations(l2): 
    i1 = iter(l1).next 
    i2 = iter(permu).next 
    row = [ i2() if i in combo else i1() for i in r ] 
    print row 

yielding:

['x', 'y', 1, 2, 3] 
['y', 'x', 1, 2, 3] 
['x', 1, 'y', 2, 3] 
['y', 1, 'x', 2, 3] 
['x', 1, 2, 'y', 3] 
['y', 1, 2, 'x', 3] 
['x', 1, 2, 3, 'y'] 
['y', 1, 2, 3, 'x'] 
[1, 'x', 'y', 2, 3] 
[1, 'y', 'x', 2, 3] 
[1, 'x', 2, 'y', 3] 
[1, 'y', 2, 'x', 3] 
[1, 'x', 2, 3, 'y'] 
[1, 'y', 2, 3, 'x'] 
[1, 2, 'x', 'y', 3] 
[1, 2, 'y', 'x', 3] 
[1, 2, 'x', 3, 'y'] 
[1, 2, 'y', 3, 'x'] 
[1, 2, 3, 'x', 'y'] 
[1, 2, 3, 'y', 'x'] 
1

Một trong những cách tốt hơn để tiếp cận này, tôi nghĩ, sẽ giữ [1,2,3] như là, và sau đó, đối với 'x', nhận ra có bốn vị trí có thể chèn vào (trước '1', trước '2', ... sau '3') . Sau đó, một khi 'x' đã được chèn vào, hiện tại có 5 vị trí để chèn 'y' (ba chữ 'x' không được chèn vào, cộng với trước 'x' và sau 'x'). Sử dụng vòng lặp lồng nhau để chèn 'x' và 'y' vào mỗi vị trí có thể. Như một phần thưởng, chưng cất vòng lặp lồng nhau thành một hiểu ...

4

Một cách để làm điều này là sử dụng itertools.combinations để chọn các chỉ mục của danh sách cuối cùng mà bạn sẽ đặt các thành phần của l1. Sau đó, đối với mỗi lựa chọn đó, hãy sử dụng itertools.permutations để tìm tất cả các hoán vị của các mục trong danh sách thứ hai. Sau đó, đi qua cả hai danh sách đó, chọn ra khỏi mặt trước hoặc tùy thuộc vào việc chỉ mục có phải là chỉ mục cho một phần tử cho l1 hoặc l2.

from itertools import combinations, permutations 

l1 = [1, 2, 3] 
l2 = ["x", "y"] 

n = len(l1) + len(l2) 

for c in combinations(range(0, n), len(l1)): 
    cs = set(c) 
    for p in permutations(l2): 
     l1i = iter(l1) 
     l2i = iter(p) 
     print [ l1i.next() if i in cs else l2i.next() for i in range(0,n) ] 

Kết quả sẽ là:

[1, 2, 3, 'x', 'y'] 
[1, 2, 3, 'y', 'x'] 
[1, 2, 'x', 3, 'y'] 
[1, 2, 'y', 3, 'x'] 
[1, 2, 'x', 'y', 3] 
[1, 2, 'y', 'x', 3] 
[1, 'x', 2, 3, 'y'] 
[1, 'y', 2, 3, 'x'] 
[1, 'x', 2, 'y', 3] 
[1, 'y', 2, 'x', 3] 
[1, 'x', 'y', 2, 3] 
[1, 'y', 'x', 2, 3] 
['x', 1, 2, 3, 'y'] 
['y', 1, 2, 3, 'x'] 
['x', 1, 2, 'y', 3] 
['y', 1, 2, 'x', 3] 
['x', 1, 'y', 2, 3] 
['y', 1, 'x', 2, 3] 
['x', 'y', 1, 2, 3] 
['y', 'x', 1, 2, 3] 
+1

Sau đó, để có được thứ tự nhất quán của '[1, 2, 3]', bạn sẽ chỉ sử dụng 'đảo ngược'? – Darthfett

+0

@ Darthfett: oops, tôi có nghĩa là 'pop (0)' thay vì 'pop()' - cố định bây giờ –

+0

Tôi nghĩ rằng 'đảo ngược' có thể cho hiệu suất tốt hơn, như' pop (0) 'là O (n), trong khi' pop() 'là O (1). Cho rằng bạn đang popping tất cả các mục từ danh sách, nó sẽ tiết kiệm tính toán (có thể là quan trọng khi bạn đang ở trong một vòng lặp hoán vị kết hợp). – Darthfett

4

tôi gọi l1 xen này với (các hoán vị của l2). Bạn có thể làm điều này theo hai bước: chọn vị trí, sau đó hoán vị trí. Đối với các điểm chèn, bạn có thể sử dụng phương pháp dựa trên mặt nạ (permutations([True,True,False,False,False])) hoặc cách tiếp cận dựa trên chỉ mục (product(*[range(5)]*2)). Chưa có kỹ thuật thứ hai để làm việc.

from itertools import * 

def interspersings(l1,l2): 
    for mask in set(permutations([0]*len(l1) + [1]*len(l2))): # sadly inefficient 
     iters = [iter(l1), iter(l2)] 
     yield [next(iters[which]) for which in mask] 

for perm in permutations(l2): 
    for interspersing in interspersings(l1,perm): 
     print(interspersing) 

Demo:

[1, 2, 'x', 'y', 3] 
['x', 'y', 1, 2, 3] 
[1, 2, 'x', 3, 'y'] 
[1, 2, 3, 'x', 'y'] 
['x', 1, 'y', 2, 3] 
[1, 'x', 'y', 2, 3] 
[1, 'x', 2, 'y', 3] 
['x', 1, 2, 'y', 3] 
[1, 'x', 2, 3, 'y'] 
['x', 1, 2, 3, 'y'] 
[1, 2, 'y', 'x', 3] 
['y', 'x', 1, 2, 3] 
[1, 2, 'y', 3, 'x'] 
[1, 2, 3, 'y', 'x'] 
['y', 1, 'x', 2, 3] 
[1, 'y', 'x', 2, 3] 
[1, 'y', 2, 'x', 3] 
['y', 1, 2, 'x', 3] 
[1, 'y', 2, 3, 'x'] 
['y', 1, 2, 3, 'x'] 

chỉnh sửa: Ah, kỹ thuật sau tôi đã đề cập được thực hiện một cách chính xác Mark Longair tại https://stackoverflow.com/a/10655695/711085 (nó được hiệu quả hơn so với kỹ thuật này)

+0

Tại sao bạn không sử dụng 'itertools.repeat' thay vì' [0] * 'và' [1] * '? – rubik

+0

@rubik: khả năng đọc được và chúng sẽ phải được mở rộng để thực hiện cuộc gọi đến 'hoán vị' – ninjagecko

+0

Sự cố đã được giải quyết. Cảm ơn bạn rất nhiều vì đã giúp đỡ. – fred

0
>>> import itertools 
>>> l1 = [1, 2, 3] 
>>> l2 = ['x', 'y', 0, 0, 0] 
>>> l4 = [] 
>>> cyc = itertools.cycle(l1) 
>>> for el in set(itertools.permutations(l2, 5)): 
...  l4.append([cyc.next() if j==0 else j for j in el]) 

sản xuất:

>>> l4 
[[1, 2, 'x', 3, 'y'], 
['y', 'x', 1, 2, 3], 
['x', 1, 'y', 2, 3], 
['x', 1, 2, 'y', 3], 
[1, 2, 3, 'y', 'x'], 
[1, 'y', 2, 3, 'x'], 
[1, 2, 3, 'x', 'y'], 
[1, 'x', 2, 3, 'y'], 
[1, 'y', 'x', 2, 3], 
[1, 2, 'x', 'y', 3], 
[1, 2, 'y', 'x', 3], 
[1, 'x', 2, 'y', 3], 
['y', 1, 2, 'x', 3], 
['x', 1, 2, 3, 'y'], 
[1, 'y', 2, 'x', 3], 
[1, 'x', 'y', 2, 3], 
['y', 1, 2, 3, 'x'], 
['x', 'y', 1, 2, 3], 
[1, 2, 'y', 3, 'x'], 
['y', 1, 'x', 2, 3]] 
Các vấn đề liên quan