2013-05-16 25 views
26

Tôi muốn tạo ra một danh sách trong python như sau -python hiểu để sản xuất hai giá trị trong một lần lặp

[1, 1, 2, 4, 3, 9, 4, 16, 5, 25 .....] 

Bạn có thể đã tìm ra, nó là gì, nhưng n, n*n

Tôi cố gắng viết như vậy một danh sách hiểu trong python như sau -

lst_gen = [i, i*i for i in range(1, 10)] 

Nhưng làm điều này, đưa ra một lỗi cú pháp.

Điều gì sẽ là một cách hay để tạo danh sách trên thông qua việc hiểu danh sách?

+1

Bạn đang gonna được đọc, giải pháp oneliner. Cảnh báo trễ được đưa ra: P – ytpillai

Trả lời

32

Sử dụng itertools.chain.from_iterable:

>>> from itertools import chain 
>>> list(chain.from_iterable((i, i**2) for i in xrange(1, 6))) 
[1, 1, 2, 4, 3, 9, 4, 16, 5, 25] 

Hoặc bạn cũng có thể sử dụng một hàm generator:

>>> def solve(n): 
...  for i in xrange(1,n+1): 
...   yield i 
...   yield i**2 

>>> list(solve(5)) 
[1, 1, 2, 4, 3, 9, 4, 16, 5, 25] 
+1

đẹp hơn của tôi :) như thường lệ: P –

5
lst_gen = sum([(i, i*i) for i in range(1, 10)],()) 

oh tôi nên đề cập đến số tiền có thể phá vỡ quy tắc một lần lặp :(

+3

Trong khi điều này sẽ làm việc, bằng cách sử dụng 'tổng hợp 'theo cách này cho hiệu suất bậc hai và do đó là một thói quen hơi nguy hiểm để rơi vào. – DSM

+0

yeah itertools sẽ tốt hơn, nhưng đôi khi tôi thích đôi khi: P –

+0

@DSM, tha thứ cho sự thiếu hiểu biết của tôi, tại sao sử dụng 'sum()' với một danh sách hiểu (tuple) cho hiệu suất bậc hai? Một phần của câu hỏi của tôi là, khía cạnh nào của "cách này" là vấn đề? – LarsH

5

Danh sách hiểu được tạo ra một phần tử tại một thời điểm. lựa chọn của bạn, thay vào đó, để thay đổi vòng lặp của bạn để chỉ tạo một giá trị cùng một thời điểm:

[(i//2)**2 if i % 2 else i//2 for i in range(2, 20)] 

hoặc để sản xuất các bộ sau đó san bằng danh sách sử dụng itertools.chain.from_iterable():

from itertools import chain 

list(chain.from_iterable((i, i*i) for i in range(1, 10))) 

Output:

>>> [(i//2)**2 if i % 2 else i//2 for i in range(2, 20)] 
[1, 1, 2, 4, 3, 9, 4, 16, 5, 25, 6, 36, 7, 49, 8, 64, 9, 81] 
>>> list(chain.from_iterable((i, i*i) for i in range(1, 10))) 
[1, 1, 2, 4, 3, 9, 4, 16, 5, 25, 6, 36, 7, 49, 8, 64, 9, 81] 
+3

Tôi không biết nếu tôi nên bị cuốn hút hoặc chán ghét bởi giải pháp đầu tiên –

1

Một tùy chọn khác:

reduce(lambda x,y: x + [y, y*y], range(1,10), []) 
+0

+1, cái này là tốt – iruvar

+0

Điều này yêu cầu nhập bằng Python 3. ('functools') – ytpillai

1

Một lựa chọn khác, có vẻ ngoan cố đối với một số

>>> from itertools import izip, tee 
>>> g = xrange(1, 11) 
>>> x, y = tee(g) 
>>> y = (i**2 for i in y) 
>>> z = izip(x, y) 
>>> output = [] 
>>> for k in z: 
...  output.extend(k) 
... 
>>> print output 
[1, 1, 2, 4, 3, 9, 4, 16, 5, 25, 6, 36, 7, 49, 8, 64, 9, 81, 10, 100] 
3

Bạn có thể tạo một danh sách liệt kê sau đó sử dụng giảm tham gia cùng họ.

print [[n,n*n] for n in range (10)] 

[[0, 0], [1, 1], [2, 4], [3, 9], [4, 16], [5, 25], [6, 36], [7, 49], [8, 64], [9, 81]]

print reduce(lambda x1,x2:x1+x2,[[n,n*n] for n in range (10)]) 

[0, 0, 1, 1, 2, 4, 3, 9, 4, 16, 5, 25, 6, 36, 7, 49, 8, 64, 9, 81]

print reduce(lambda x1,x2:x1+x2,[[n**e for e in range(1,4)]\ 
for n in range (1,10)]) 

[1, 1, 2, 4, 8, 3, 9, 27, 4, 16, 64, 5, 25, 125, 6, 36, 216, 7, 49, 343, 8, 64, 512, 9, 81, 729]

Giảm mất một biểu thức có thể gọi mà phải mất hai đối số và xử lý một chuỗi bằng cách bắt đầu với hai mục đầu tiên. Kết quả của biểu thức cuối cùng sau đó được sử dụng làm mục đầu tiên trong các cuộc gọi tiếp theo. Trong trường hợp này, mỗi danh sách được thêm một cái khác vào danh sách đầu tiên trong danh sách các danh sách và sau đó danh sách đó được trả về kết quả.

Danh sách

comprehensions ngầm gọi bản đồ với một biểu thức lambda sử dụng biến và trình tự xác định bởi "cho var trong chuỗi" biểu. Sau đây là cùng một loại điều.

map(lambda n:[n,n*n],range(1,10)) 

[[1, 1], [2, 4], [3, 9], [4, 16], [5, 25], [6, 36], [7, 49], [8, 64], [9, 81]]

Tôi không biết về biểu thức python tự nhiên hơn để giảm.

0
>>> lst_gen = [[i, i*i] for i in range(1, 10)] 
>>> 
>>> lst_gen 
[[1, 1], [2, 4], [3, 9], [4, 16], [5, 25], [6, 36], [7, 49], [8, 64], [9, 81]] 
>>> 
>>> [num for elem in lst_gen for num in elem] 
[1, 1, 2, 4, 3, 9, 4, 16, 5, 25, 6, 36, 7, 49, 8, 64, 9, 81] 

Đây là tài liệu tham khảo của tôi http://docs.python.org/2/tutorial/datastructures.html

0

Hãy thử hai lót này

lst = [[i, i*i] for i in range(10)] 
[lst.extend(i) for i in lst] 

Thay đổi toán học khi cần thiết.

Thậm chí tốt hơn

#Change my_range to be the number you want range() function of 
start = 1 
my_range = 10 
lst = [i/2 if i % 2 == 0 else ((i-1)/2)**2 for i in range(start *2, my_range*2 - 1)] 
0

Như đã đề cập, itertools là con đường để đi. Đây là cách tôi sẽ làm điều đó, tôi thấy nó rõ ràng hơn:

[i if turn else i*i for i,turn in itertools.product(range(1,10), [True, False])] 
1

Câu hỏi đặt ra là cũ, nhưng chỉ dành riêng cho người đọc tò mò, tôi đề xuất một khả năng khác: Như đã nêu trên bài viết đầu tiên, bạn có thể dễ dàng thực hiện một vài (i, i ** 2) từ danh sách các số. Sau đó, bạn muốn san bằng cặp đôi này. Vì vậy, chỉ cần thêm các hoạt động flatten trong hiểu của bạn.

[x for i in range(1, 10) for x in (i,i**2)] 
1

Một mẹo nhỏ: danh sách hiểu biết có thể có nhiều điều khoản.

Ví dụ:

>>> [10*x+y for x in range(4) for y in range(3)] 
[0, 1, 2, 10, 11, 12, 20, 21, 22, 30, 31, 32] 

Trong trường hợp cụ thể của bạn, bạn có thể làm:

>>> [x*x if y else x for x in range(5) for y in range(2)] 
[0, 0, 1, 1, 2, 4, 3, 9, 4, 16] 
Các vấn đề liên quan