Dòng đơn lồng nhau cho vòng lặp


102

Đã viết hàm này trong python để chuyển đổi một ma trận:

def transpose(m):
    height = len(m)
    width = len(m[0])
    return [ [ m[i][j] for i in range(0, height) ] for j in range(0, width) ]

Trong quá trình này, tôi nhận ra rằng tôi không hoàn toàn hiểu cách thực thi của một dòng đơn lồng nhau cho các vòng lặp. Vui lòng giúp tôi hiểu bằng cách trả lời các câu hỏi sau:

  1. Thứ tự thực thi vòng lặp for này là gì?
  2. Nếu tôi có ba vòng lặp for lồng vào nhau, thứ tự nào nó sẽ thực thi?
  3. Điều gì sẽ bằng với vòng lặp for unnested bằng nhau?

Được,

[ function(i,j) for i,j in object ]
  1. Đối tượng phải là kiểu gì để sử dụng cấu trúc vòng lặp for này?
  2. Thứ tự mà i và j được gán cho các phần tử trong đối tượng là gì?
  3. Nó có thể được mô phỏng bằng một cấu trúc vòng lặp for khác không?
  4. Vòng lặp for này có thể được lồng với một cấu trúc tương tự hay khác với vòng lặp for? Và nó sẽ trông như thế nào?

Thông tin bổ sung cũng được đánh giá cao.

Câu trả lời:


169

Nguồn thông tin tốt nhất là hướng dẫn Python chính thức về hiểu danh sách . Khả năng hiểu danh sách gần giống như vòng lặp for (chắc chắn bất kỳ cách hiểu danh sách nào cũng có thể được viết dưới dạng vòng lặp for) nhưng chúng thường nhanh hơn so với sử dụng vòng lặp for.

Xem phần đọc hiểu danh sách dài hơn này từ hướng dẫn ( ifphần lọc phần đọc hiểu, chỉ những phần vượt qua câu lệnh if mới được chuyển vào phần cuối cùng của phần đọc hiểu danh sách (tại đây (x,y)):

>>> [(x, y) for x in [1,2,3] for y in [3,1,4] if x != y]
[(1, 3), (1, 4), (2, 3), (2, 1), (2, 4), (3, 1), (3, 4)]

Nó hoàn toàn giống với vòng lặp for lồng nhau này (và, như hướng dẫn đã nói, hãy lưu ý thứ tự của for và if giống nhau).

>>> combs = []
>>> for x in [1,2,3]:
...     for y in [3,1,4]:
...         if x != y:
...             combs.append((x, y))
...
>>> combs
[(1, 3), (1, 4), (2, 3), (2, 1), (2, 4), (3, 1), (3, 4)]

Sự khác biệt chính giữa khả năng hiểu danh sách và vòng lặp for là phần cuối cùng của vòng lặp for (nơi bạn làm việc gì đó) xuất hiện ở đầu chứ không phải ở cuối.

Về câu hỏi của bạn:

Đối tượng phải là kiểu gì để sử dụng cấu trúc vòng lặp for này?

Có thể lặp lại . Bất kỳ đối tượng nào có thể tạo ra một tập hợp phần tử (hữu hạn). Chúng bao gồm bất kỳ vùng chứa, danh sách, bộ, trình tạo, v.v.

Thứ tự mà i và j được gán cho các phần tử trong đối tượng là gì?

Chúng được chỉ định theo thứ tự chính xác khi chúng được tạo từ mỗi danh sách, như thể chúng nằm trong vòng lặp for lồng nhau (đối với lần đọc đầu tiên của bạn, bạn sẽ nhận được 1 phần tử cho i, sau đó mọi giá trị từ j, phần tử thứ 2 thành i, sau đó mọi giá trị từ j, v.v.)

Nó có thể được mô phỏng bằng một cấu trúc vòng lặp for khác không?

Có, đã được hiển thị ở trên.

Vòng lặp for này có thể được lồng với một cấu trúc tương tự hay khác với vòng lặp for? Và nó sẽ trông như thế nào?

Chắc chắn, nhưng nó không phải là một ý tưởng tuyệt vời. Ví dụ ở đây, cung cấp cho bạn một danh sách các ký tự:

[[ch for ch in word] for word in ("apple", "banana", "pear", "the", "hello")]

Tôi tự hỏi điều gì đã hướng dẫn họ lựa chọn đặt hàng trong lồng đôi. Tôi thấy cách khác tự nhiên hơn (đối với y sau đó đối với x trong ví dụ của bạn). Tôi chỉ nhận ra rằng sau 3 năm làm python (không rộng rãi nhưng vẫn ...) và sử dụng các loại vòng lặp !!
Thomas

@Thomas Tôi cũng thấy cách khác trực quan hơn. Sự lựa chọn mà tôi tin rằng hoàn toàn là sự tiện lợi. Làm theo cách trực quan hơn có nghĩa là phải xử lý các ký hiệu chưa được giải quyết cho đến khi tìm thấy chúng sau này trong câu lệnh. Hãy thử phân tích cú pháp cho từng quả chuối.peel trong mỗi quả chuối cho mỗi thành phố.bananastore ở mỗi thành phố trên giấy. Không dễ dàng. Ngược lại, tốt và dễ dàng.
Pyjong

29

Bạn có thể quan tâm itertools.product, nó sẽ trả về một bộ giá trị có thể lặp lại có năng suất từ ​​tất cả các vòng lặp mà bạn chuyển nó. Nghĩa là, itertools.product(A, B)sinh ra tất cả các giá trị của biểu mẫu (a, b), nơi các agiá trị đến Abgiá trị đến từ đâu B. Ví dụ:

import itertools

A = [50, 60, 70]
B = [0.1, 0.2, 0.3, 0.4]

print [a + b for a, b in itertools.product(A, B)]

Bản in này:

[50.1, 50.2, 50.3, 50.4, 60.1, 60.2, 60.3, 60.4, 70.1, 70.2, 70.3, 70.4]

Lưu ý cách đối số cuối cùng được truyền đến itertools.productlà đối số "bên trong". Nói chung, bằngitertools.product(a0, a1, ... an)[(i0, i1, ... in) for in in an for in-1 in an-1 ... for i0 in a0]


4

Trước hết, mã đầu tiên của bạn không sử dụng vòng lặp for mà là một danh sách dễ hiểu .

  1. Sẽ tương đương với

    đối với j trong phạm vi (0, chiều rộng): đối với tôi trong phạm vi (0, chiều cao): m [i] [j]

  2. Cũng giống như vậy, nó thường tổ chức giống như vòng lặp for, từ phải sang trái. Nhưng cú pháp hiểu danh sách phức tạp hơn.

  3. Tôi không chắc câu hỏi này đang hỏi là gì


  1. Bất kỳ đối tượng có thể lặp lại nào mang lại các đối tượng có thể lặp lại mang lại chính xác hai đối tượng (thật tuyệt - tức là [(1,2),'ab']sẽ hợp lệ)

  2. Thứ tự mà đối tượng sinh ra khi lặp lại. iđi đến sản lượng đầu tiên, jthứ hai.

  3. Có, nhưng không đẹp. Tôi tin rằng nó có chức năng tương đương với:

    l = list ()
    cho i, j trong đối tượng:
        l.append (function (i, j))
    

    hoặc thậm chí sử dụng bản đồ tốt hơn :

    map(function, object)

    Nhưng tất nhiên chức năng sẽ phải nhận được i, jchính nó.

  4. Đây không phải là câu hỏi giống với số 3 sao?


2

Bạn có thể sử dụng hai vòng lặp for trên cùng một dòng bằng cách sử dụng ziphàm

Mã:

list1 = ['Abbas', 'Ali', 'Usman']
list2 = ['Kamran', 'Asgar', 'Hamza', 'Umer']
list3 = []
for i,j in zip(list1,list2):
    list3.append(i)
    list3.append(j)
print(list3)

Đầu ra:

['Abbas', 'Kamran', 'Ali', 'Asgar', 'Usman', 'Hamza']

Vì vậy, bằng cách sử dụng hàm zip, chúng ta có thể sử dụng hai vòng lặp for hoặc chúng ta có thể lặp lại hai danh sách trong cùng một hàng.


-1

Dưới đây là mã cho các ví dụ tốt nhất cho các vòng lặp lồng nhau, trong khi sử dụng hai vòng lặp for, hãy nhớ đầu ra của vòng lặp đầu tiên là đầu vào cho vòng lặp thứ hai. Kết thúc vòng lặp cũng quan trọng khi sử dụng các vòng lặp lồng nhau

for x in range(1, 10, 1):
     for y in range(1,x):
             print y,
        print
OutPut :
1
1 2
1 2 3
1 2 3 4
1 2 3 4 5
1 2 3 4 5 6
1 2 3 4 5 6 7
1 2 3 4 5 6 7 8
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.