Computer >> Máy Tính >  >> Lập trình >> Python

Cách xử lý song song các trình vòng lặp bằng ZIP

Giới thiệu

Khả năng hiểu danh sách giúp dễ dàng lấy danh sách nguồn và lấy danh sách dẫn xuất bằng cách áp dụng một biểu thức. Ví dụ:giả sử tôi muốn nhân từng phần tử trong danh sách với 5. Ở đây, tôi thực hiện việc này bằng cách sử dụng vòng lặp for đơn giản.

a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
multiply_by_5 = []
for x in a:
multiply_by_5.append(x*5)
print(f"Output \n *** {multiply_by_5}")

Đầu ra

*** [5, 10, 15, 20, 25, 30, 35, 40, 45, 50]

Với khả năng hiểu danh sách, tôi có thể đạt được kết quả tương tự bằng cách chỉ định biểu thức và chuỗi đầu vào để lặp lại.

# List comprehension
multiply_by_5 = [x*2 for x in a]
print(f"Output \n *** {multiply_by_5}")

Đầu ra

*** [2, 4, 6, 8, 10, 12, 14, 16, 18, 20]

Bây giờ, hãy để chúng tôi nói rằng bạn có một vài danh sách để bổ sung.

# 1 . Create a List of Numbers
list1 = [100, 200, 300, 400]
list2 = [500, 600, 700, 800]

# 2. Add the two lists to create a new list
list3 = []

# Using a Loop.
for i in range(len(list1)):
added_value = list1[i] + list2[i]
list3.append(added_value)
print(f"Output \n*** {list3}")

Đầu ra

*** [600, 800, 1000, 1200]

Bây giờ điều quan trọng ở đây là các mục trong danh sách dẫn xuất (trong trường hợp của chúng tôi là list3) các giá trị được thêm vào có liên quan trực tiếp đến các mục trong danh sách nguồn theo chỉ mục của chúng.

Bây giờ theo cách nén, đây là một giải pháp zip cho các số nguyên trong cùng một danh sách. Trong trường hợp này, hai danh sách các số nguyên, một danh sách chứa 100, 200, 300 và 400 và một danh sách chứa 500, 600, 700 và 800. Và tất nhiên, chúng ta có thể xác định chúng và gán chúng cho các biến. Và chúng không cần phải là danh sách.

Chúng có thể là các chuỗi khác, chẳng hạn như các bộ giá trị, v.v.

Vì vậy, những gì chúng ta sẽ làm là nén các cặp phần tử từ chúng lại với nhau, vì vậy 100 từ list1 và 500 từ list2 sẽ được nén lại với nhau, v.v. Đối với mỗi tuple, khi chúng tôi lặp qua chúng, chúng tôi sẽ giải nén bộ tuple thành các biến a và b.

list4 = []
list4 = [(a + b) for a, b in zip(list1, list2)]
print(f"Output \n*** {list4}")

Đầu ra

*** [600, 800, 1000, 1200]

Bây giờ giải pháp trên trông thực sự tuyệt vời, tuy nhiên có một vấn đề nghiêm trọng bạn cần biết trước khi áp dụng chúng trong mã của mình.

Hàm tích hợp sẵn zip hoạt động lạ nếu các trình vòng lặp đầu vào có độ dài khác nhau. Hãy để chúng tôi thử chúng.

# add a new number to the list
list1.append(1000)
print(f"Output \n*** Length of List1 is {len(list1)} , Length of List2 is {len(list2)}")

# run the zip against the list for addition.
list5 = [(a + b) for a, b in zip(list1, list2)]
print(f"*** {list5}")

Đầu ra

*** Length of List1 is 9 , Length of List2 is 4
*** [600, 800, 1000, 1200]

Bây giờ khi chúng tôi in ra từng số đã thêm từ list3, bạn sẽ nhận thấy rằng số được thêm vào list1 bị thiếu, mặc dù chúng tôi đã thêm nó vào đó và nó trong list1 nó không hiển thị trong đầu ra của zip.

Và đây chỉ là cách zip hoạt động. Nó giữ cho bạn trong các bộ giá trị cho đến khi bất kỳ, một trong hai trình vòng lặp bị cạn kiệt. Vì vậy, mặc dù list1 có nhiều thứ hơn để đi so với list2, trước tiên nó sẽ cạn kiệt và sau đó vòng lặp sẽ thoát ra.

Đáng ngạc nhiên là bạn không được thông báo với bất kỳ ngoại lệ nào. Vì vậy, bạn phải rất cẩn thận với mã zip trong quá trình sản xuất.

Bạn có một tùy chọn cho sự cố này trong hàm python từ itertools được gọi là zip lâu nhất.

Zip này dài nhất là gì, nó vẫn tiếp tục ngay cả khi một trong các trình vòng lặp đã hết.

from itertools import zip_longest

list6 = []
for a, b in zip_longest(list1, list2):
if b is None:
print(f" << do your logic here >> ")
elif a is None:
print(f" << do your logic here >> ")
else:
list6.append(a + b)
print(f"Output \n*** {list6}")


<< do your logic here >>
<< do your logic here >>
<< do your logic here >>
<< do your logic here >>
<< do your logic here >>

Đầu ra

*** [600, 800, 1000, 1200]

Kết luận:

  • Hàm zip rất tiện dụng nếu bạn muốn lặp song song nhiều trình vòng lặp.

  • hàm zip hoạt động khác nhau khi bạn chuyển các trình vòng lặp có độ dài khác nhau.

  • Trong trường hợp bạn muốn sử dụng các trình vòng lặp có độ dài khác nhau, hãy sử dụng zip_longest.