Lời tựa
Các vòng lặp lồng nhau không phải là một điều xấu mỗi se. Chúng chỉ xấu, nếu có được sử dụng cho các vấn đề, trong đó thuật toán tốt hơn đã được tìm thấy [tốt hơn và xấu về hiệu quả liên quan đến kích thước đầu vào]. Sắp xếp một danh sách các số nguyên chẳng hạn là một vấn đề như vậy.
Phân tích vấn đề
Kích cỡ
Trong trường hợp của bạn ở trên, bạn có ba danh sách, tất cả kích thước 4. Điều này tạo ra 4 * 4 * 4 = 64 Các kết hợp có thể của chúng, nếu A luôn đến trước B và B trước c. Vì vậy, bạn cần ít nhất 64 lần lặp lại!
Cách tiếp cận của bạn
Theo cách tiếp cận của bạn, chúng tôi có 4 lần lặp cho từng giá trị có thể của A, 4 lần lặp cho từng giá trị có thể có của B và giống nhau cho c. Vì vậy, chúng tôi có tổng cộng 4 * 4 * 4 = 64. Vì vậy, trong thực tế, giải pháp của bạn là khá tốt! Vì không có cách nghe nhanh hơn tất cả các kết hợp, cách của bạn cũng là cách tốt nhất.
Phong cách
Về phong cách người ta có thể nói rằng bạn có thể cải thiện mã của mình bằng các tên biến tốt hơn và kết hợp một số vòng lặp. Ví dụ. như thế:
def replaceVar[expressions]:
"""
Takes a list of expressions and returns a list of expressions with
evaluated variables.
"""
evaluatedExpressions = list[]
valuesOfA = [1, 8, 12, 13]
valuesOfB = [1, 2, 3, 4]
valuesOfC = [5, 9, 2, 7]
for expression in expressions:
for valueOfA in valuesOfA:
for valueOfB in valuesOfB:
for valueOfC in valuesOfC:
newExpression = expression.\
replace['a', str[valueOfA]].\
replace['b', str[valueOfB]].\
replace['c', str[valueOfC]]
evaluatedExpressions.append[newExpression]
print[evaluatedExpressions]
return evaluatedExpressions
print[replaceVar[['b-16+[c-[a+11]]', 'a-[c-5]+a-b-10']]]
Tuy nhiên, lưu ý rằng số lượng lặp vẫn giữ nguyên!
Itertools
Như Kevin nhận thấy, bạn cũng có thể sử dụng
import itertools
def replaceVar[expressions]:
"""
Takes a list of expressions and returns a list of expressions with
evaluated variables.
"""
evaluatedExpressions = list[]
valuesOfA = [1, 8, 12, 13]
valuesOfB = [1, 2, 3, 4]
valuesOfC = [5, 9, 2, 7]
for expression in expressions:
for values in itertools.product[valuesOfA, valuesOfB, valuesOfC]:
valueOfA = values[0]
valueOfB = values[1]
valueOfC = values[2]
newExpression = expression.\
replace['a', str[valueOfA]].\
replace['b', str[valueOfB]].\
replace['c', str[valueOfC]]
evaluatedExpressions.append[newExpression]
print[evaluatedExpressions]
return evaluatedExpressions
print[replaceVar[['b-16+[c-[a+11]]', 'a-[c-5]+a-b-10']]]
3 để tạo ra sản phẩm Cartesian. Trong nội bộ, nó sẽ làm giống như những gì bạn đã làm với các vòng lặp kết hợp:import itertools
def replaceVar[expressions]:
"""
Takes a list of expressions and returns a list of expressions with
evaluated variables.
"""
evaluatedExpressions = list[]
valuesOfA = [1, 8, 12, 13]
valuesOfB = [1, 2, 3, 4]
valuesOfC = [5, 9, 2, 7]
for expression in expressions:
for values in itertools.product[valuesOfA, valuesOfB, valuesOfC]:
valueOfA = values[0]
valueOfB = values[1]
valueOfC = values[2]
newExpression = expression.\
replace['a', str[valueOfA]].\
replace['b', str[valueOfB]].\
replace['c', str[valueOfC]]
evaluatedExpressions.append[newExpression]
print[evaluatedExpressions]
return evaluatedExpressions
print[replaceVar[['b-16+[c-[a+11]]', 'a-[c-5]+a-b-10']]]
Các vòng lặp làm tổ bên trong nhau trong Python làm cho mã khó hiểu hơn nhiều, cần có nhiều sức mạnh não hơn để hiểu, và do đó dễ bị lỗi hơn so với việc có thể tránh được. Một vấn đề với sự phức tạp này là các ví dụ đồ chơi có thể có ý nghĩa, nhưng hầu hết các ví dụ thực tế sẽ phát triển và trở nên được lồng sâu hơn theo thời gian. Tránh sự phức tạp này ngay từ đầu có thể giúp đơn giản hóa dự án trong tương lai.
thành lập
Hãy lấy một ví dụ khá đơn giản, nơi chúng tôi đang sử dụng một thư viện Ficticy để lấy một số dữ liệu bán hàng cho công ty vận chuyển của chúng tôi. API cho phép chúng tôi tìm nạp dữ liệu bán hàng TEH cho một loại xe và một khu vực tại một thời điểm.
import pandas as pd
from datastore import get_sales # ficticious library
cars = ['sedan', 'coupe', 'hatchback']
regions = ['US', 'CA', 'MX']
Vòng lặp làm tổ
Chúng tôi đã thiết lập để tìm nạp dữ liệu của chúng tôi với hai danh sách đại diện cho các phương tiện và khu vực mà chúng tôi muốn phân tích. Chúng tôi biết rằng chúng tôi cần thực hiện một cuộc gọi đến
import itertools
def replaceVar[expressions]:
"""
Takes a list of expressions and returns a list of expressions with
evaluated variables.
"""
evaluatedExpressions = list[]
valuesOfA = [1, 8, 12, 13]
valuesOfB = [1, 2, 3, 4]
valuesOfC = [5, 9, 2, 7]
for expression in expressions:
for values in itertools.product[valuesOfA, valuesOfB, valuesOfC]:
valueOfA = values[0]
valueOfB = values[1]
valueOfC = values[2]
newExpression = expression.\
replace['a', str[valueOfA]].\
replace['b', str[valueOfB]].\
replace['c', str[valueOfC]]
evaluatedExpressions.append[newExpression]
print[evaluatedExpressions]
return evaluatedExpressions
print[replaceVar[['b-16+[c-[a+11]]', 'a-[c-5]+a-b-10']]]
4 cho mọi phương tiện và khu vực nên các vòng làm tổ là một giải pháp đầu tiên rất phổ biến để nhảy đến.sales = pd.DataFrame[]
for car in cars:
for region in regions:
new_sales = get_sales[car, region]
sales = pd.concat[[sales, new_sales]]
Python cung cấp cho chúng tôi mô -đun ITERtools đẹp cho phép chúng tôi chuẩn bị đầu vào cho việc này theo cách SUSYNCT hơn nhiều. Chức năng sản phẩm của itertools sẽ cung cấp cho chúng ta mọi sự kết hợp của bất kỳ số lượng lặp đi lặp lại
import itertools
list[itertools.product[cars, regions]]
Lưu ý rằng itertools trả về một trình tạo cho hầu hết nếu không phải tất cả các hàm, danh sách [] sẽ biến nó thành một danh sách mà chúng ta có thể thấy. Điều này hoạt động tuyệt vời cho các bộ dữ liệu nhỏ, nhưng có thể không được khuyến khích trên các bộ dữ liệu lớn hơn.
đầu ra
[['sedan', 'US'],
['sedan', 'CA'],
['sedan', 'MX'],
['coupe', 'US'],
['coupe', 'CA'],
['coupe', 'MX'],
['hatchback', 'US'],
['hatchback', 'CA'],
['hatchback', 'MX']]
Bây giờ chúng tôi có mọi sự kết hợp của hai bộ đầu vào trong một danh sách duy nhất, chúng tôi có thể lặp lại danh sách đó một lần.
sales = pd.DataFrame[]
for car, region in itertools.product[cars, regions]:
new_sales = get_sales[car, region]
sales = pd.concat[[sales, new_sales]]
Trên đây theo sau một bản chống Python, khởi tạo sau đó chỉnh sửa. Trong một số trường hợp, có thể dễ đọc hơn một chút để làm theo cách đó, bạn có thể là thẩm phán, nhưng trong trường hợp đơn giản của chúng tôi, chúng tôi có thể chỉ cần đạt được kết quả tương tự bằng cách sử dụng danh sách hiểu.
pd.concat[[get_sales[cars, region] for cars, region in itertools.product[cars, regions]]]
Từ điển
sales_args = {
'cars': ['sedan', 'coupe', 'hatchback'],
'regions': ['US', 'CA', 'MX'],
}
pd.concat[[get_sales[*sales_arg] for sales_arg in itertools.product[*sales_args.values[]]]]
sales_args = {
'cars': ['sedan', 'coupe', 'hatchback'],
'regions': ['US', 'CA', 'MX'],
'month': ['MAR', 'APR', 'MAY']
}
pd.concat[[get_sales[*sales_arg] for sales_arg in product[*sales_args.values[]]]]
Chuỗi
thùng chứa của container
import itertools
def replaceVar[expressions]:
"""
Takes a list of expressions and returns a list of expressions with
evaluated variables.
"""
evaluatedExpressions = list[]
valuesOfA = [1, 8, 12, 13]
valuesOfB = [1, 2, 3, 4]
valuesOfC = [5, 9, 2, 7]
for expression in expressions:
for values in itertools.product[valuesOfA, valuesOfB, valuesOfC]:
valueOfA = values[0]
valueOfB = values[1]
valueOfC = values[2]
newExpression = expression.\
replace['a', str[valueOfA]].\
replace['b', str[valueOfB]].\
replace['c', str[valueOfC]]
evaluatedExpressions.append[newExpression]
print[evaluatedExpressions]
return evaluatedExpressions
print[replaceVar[['b-16+[c-[a+11]]', 'a-[c-5]+a-b-10']]]
0import itertools
def replaceVar[expressions]:
"""
Takes a list of expressions and returns a list of expressions with
evaluated variables.
"""
evaluatedExpressions = list[]
valuesOfA = [1, 8, 12, 13]
valuesOfB = [1, 2, 3, 4]
valuesOfC = [5, 9, 2, 7]
for expression in expressions:
for values in itertools.product[valuesOfA, valuesOfB, valuesOfC]:
valueOfA = values[0]
valueOfB = values[1]
valueOfC = values[2]
newExpression = expression.\
replace['a', str[valueOfA]].\
replace['b', str[valueOfB]].\
replace['c', str[valueOfC]]
evaluatedExpressions.append[newExpression]
print[evaluatedExpressions]
return evaluatedExpressions
print[replaceVar[['b-16+[c-[a+11]]', 'a-[c-5]+a-b-10']]]
1import itertools
def replaceVar[expressions]:
"""
Takes a list of expressions and returns a list of expressions with
evaluated variables.
"""
evaluatedExpressions = list[]
valuesOfA = [1, 8, 12, 13]
valuesOfB = [1, 2, 3, 4]
valuesOfC = [5, 9, 2, 7]
for expression in expressions:
for values in itertools.product[valuesOfA, valuesOfB, valuesOfC]:
valueOfA = values[0]
valueOfB = values[1]
valueOfC = values[2]
newExpression = expression.\
replace['a', str[valueOfA]].\
replace['b', str[valueOfB]].\
replace['c', str[valueOfC]]
evaluatedExpressions.append[newExpression]
print[evaluatedExpressions]
return evaluatedExpressions
print[replaceVar[['b-16+[c-[a+11]]', 'a-[c-5]+a-b-10']]]
2Đầu ra
import itertools
def replaceVar[expressions]:
"""
Takes a list of expressions and returns a list of expressions with
evaluated variables.
"""
evaluatedExpressions = list[]
valuesOfA = [1, 8, 12, 13]
valuesOfB = [1, 2, 3, 4]
valuesOfC = [5, 9, 2, 7]
for expression in expressions:
for values in itertools.product[valuesOfA, valuesOfB, valuesOfC]:
valueOfA = values[0]
valueOfB = values[1]
valueOfC = values[2]
newExpression = expression.\
replace['a', str[valueOfA]].\
replace['b', str[valueOfB]].\
replace['c', str[valueOfC]]
evaluatedExpressions.append[newExpression]
print[evaluatedExpressions]
return evaluatedExpressions
print[replaceVar[['b-16+[c-[a+11]]', 'a-[c-5]+a-b-10']]]
5