Python中嵌套的`for`循环的替代方法

Python中嵌套的`for`循环的替代方法,python,Python,我试图比较从文件中读取的禁止文件夹列表。但我们必须检查任务是否具有文件夹的父ID,然后检查该文件夹是否与禁止的文件夹匹配。我循环浏览的列表可以包含许多项 for task in tasks: #Check the task is on their timesheet if task["id"] == entry["item_id"]: for folder in folders: #See if the task is inside the

我试图比较从文件中读取的禁止文件夹列表。但我们必须检查任务是否具有文件夹的父ID,然后检查该文件夹是否与禁止的文件夹匹配。我循环浏览的列表可以包含许多项

for task in tasks:
    #Check the task is on their timesheet
    if task["id"] == entry["item_id"]:
        for folder in folders:
            #See if the task is inside the folder
            if task["parent_id"] == folder["id"]:
                for forbiddenFolder in forbiddenFolders:
                    #If the folder is on the list
                    if forbiddenFolder == folder["name"]:
                        body_of_email +=( "Using a task within a folder that is not permiited " + forbiddenFolder + "\r\n" )
                        folder["name"]
                        break

此代码使用三个嵌套的
进行
循环,这可能会很慢。我可以提高效率吗?

您可以减少代码行数,并使其更易于理解,如下所示:

tasks_id = [task in tasks if task["id"] == entry["item_id"]]
folders_dict = dict()
for folder in folders:
    folders_dict[folder["id"]] = folder

for task in tasks_id:
    if task["parent_id"] in folders_dict.keys() and folder_dict[task["parent_id"]] in forbiddenFolders:
        body_of_email +=( "Using a task within a folder that is not permiited " + forbiddenFolder + "\r\n" )

您可以减少代码行数并使其更易于理解,如下所示:

tasks_id = [task in tasks if task["id"] == entry["item_id"]]
folders_dict = dict()
for folder in folders:
    folders_dict[folder["id"]] = folder

for task in tasks_id:
    if task["parent_id"] in folders_dict.keys() and folder_dict[task["parent_id"]] in forbiddenFolders:
        body_of_email +=( "Using a task within a folder that is not permiited " + forbiddenFolder + "\r\n" )

这里您要做的是根据id查找项目(任务、文件夹)。Python字典提供了一种简单的方法。只有在执行多次搜索时(例如,如果有许多任务具有相同的id,或者如果要多次运行该函数),才会保存

此外,对于禁止使用的文件夹,您只有一个名称列表(您没有查找项目,您只是检查它是否存在),Python的集合适用于该列表

无论如何,以下是构建字典和集合的方法:

tasks_dict = dict((task['id'], task) for task in tasks)
folders_dict = dict((folder['id'], folder) for folder in folders)
forbidden_folders_set = set(forbiddenFolders)
现在,
task=tasks\u dict[id]
是这样一个任务:
task['id']==id
,对于文件夹也是如此,因此您可以用这些表达式替换上面的循环。集合不允许这样做,但它允许您使用禁止的文件夹集合中的
文件夹检查是否存在

(请记住,这些
dict(…)
操作中的每一个都可能比运行上述for循环中的一个要花更长的时间,但它们是未来更快查找的投资。)


上面的
x-in-y
..\u dict[x]
操作非常有效。

这里尝试的是根据id查找项目(任务、文件夹)。Python字典提供了一种简单的方法。只有在执行多次搜索时(例如,如果有许多任务具有相同的id,或者如果要多次运行该函数),才会保存

此外,对于禁止使用的文件夹,您只有一个名称列表(您没有查找项目,您只是检查它是否存在),Python的集合适用于该列表

无论如何,以下是构建字典和集合的方法:

tasks_dict = dict((task['id'], task) for task in tasks)
folders_dict = dict((folder['id'], folder) for folder in folders)
forbidden_folders_set = set(forbiddenFolders)
现在,
task=tasks\u dict[id]
是这样一个任务:
task['id']==id
,对于文件夹也是如此,因此您可以用这些表达式替换上面的循环。集合不允许这样做,但它允许您使用禁止的文件夹集合中的
文件夹检查是否存在

(请记住,这些
dict(…)
操作中的每一个都可能比运行上述for循环中的一个要花更长的时间,但它们是未来更快查找的投资。)


上面的
x in y
..\u dict[x]
操作非常有效。

让您保留原始数据结构的方法如下:

for task in (t for t in tasks if entry["item_id"]==t["id"]):
    for folder in (f for f in folders if task["parent_id"]==f["id"]):
        for forbiddenFolder in (ff for ff in forbiddenFolders if ff==folder["name"]):
            body_of_email += "Using a task within a folder that is not permitted %s \r\n"% forbiddenFolder
            break
tasks = {
    'design': 'later',
    'testing': 'desired',
    'vacation': 'fall'
}

folders = {
    'summer': 'red',
    'fall': 'gold',
    'winter': 'white',
    'spring': 'green'
}

def apply_some_logic(a, b, c, d):
    return '_'.join([a, b, c, d]) if b == c else (a, b, c, d)


if __name__ == '__main__':
    results = (apply_some_logic(a, b, c, d) for a, b in tasks.items() for c, d in folders.items())
    for result in results:
        print(result)


$ python3.6 --version
Python 3.6.4

output:
('design', 'later', 'Summer', 'Red')
('design', 'later', 'Fall', 'Gold')
('design', 'later', 'Winter', 'White')
('design', 'later', 'Spring', 'Green')
('implementation', 'urgent', 'Summer', 'Red')
('implementation', 'urgent', 'Fall', 'Gold')
('implementation', 'urgent', 'Winter', 'White')
('implementation', 'urgent', 'Spring', 'Green')
('testing', 'desired', 'Summer', 'Red')
('testing', 'desired', 'Fall', 'Gold')
('testing', 'desired', 'Winter', 'White')
('testing', 'desired', 'Spring', 'Green')
('vacation', 'Fall', 'Summer', 'Red')
vacation_Fall_Fall_Gold
('vacation', 'Fall', 'Winter', 'White')
('vacation', 'Fall', 'Spring', 'Green')

这就利用了非常高效的内存,从而保持了速度,并且在条件
的情况下,在范围(y)内,对于x的形式为
x的循环是有条件的。我建议两个都看看

让您保留原始数据结构的方法如下:

for task in (t for t in tasks if entry["item_id"]==t["id"]):
    for folder in (f for f in folders if task["parent_id"]==f["id"]):
        for forbiddenFolder in (ff for ff in forbiddenFolders if ff==folder["name"]):
            body_of_email += "Using a task within a folder that is not permitted %s \r\n"% forbiddenFolder
            break
tasks = {
    'design': 'later',
    'testing': 'desired',
    'vacation': 'fall'
}

folders = {
    'summer': 'red',
    'fall': 'gold',
    'winter': 'white',
    'spring': 'green'
}

def apply_some_logic(a, b, c, d):
    return '_'.join([a, b, c, d]) if b == c else (a, b, c, d)


if __name__ == '__main__':
    results = (apply_some_logic(a, b, c, d) for a, b in tasks.items() for c, d in folders.items())
    for result in results:
        print(result)


$ python3.6 --version
Python 3.6.4

output:
('design', 'later', 'Summer', 'Red')
('design', 'later', 'Fall', 'Gold')
('design', 'later', 'Winter', 'White')
('design', 'later', 'Spring', 'Green')
('implementation', 'urgent', 'Summer', 'Red')
('implementation', 'urgent', 'Fall', 'Gold')
('implementation', 'urgent', 'Winter', 'White')
('implementation', 'urgent', 'Spring', 'Green')
('testing', 'desired', 'Summer', 'Red')
('testing', 'desired', 'Fall', 'Gold')
('testing', 'desired', 'Winter', 'White')
('testing', 'desired', 'Spring', 'Green')
('vacation', 'Fall', 'Summer', 'Red')
vacation_Fall_Fall_Gold
('vacation', 'Fall', 'Winter', 'White')
('vacation', 'Fall', 'Spring', 'Green')

这就利用了非常高效的内存,从而保持了速度,并且在条件
的情况下,在范围(y)内,对于x的形式为
x的循环是有条件的。我建议两个都看看

从原始调查中复杂的细节后退一步, 并将注意力放在中的一些“嵌套for循环的替代方案”上 一般情况下,以下各项如何:

for task in (t for t in tasks if entry["item_id"]==t["id"]):
    for folder in (f for f in folders if task["parent_id"]==f["id"]):
        for forbiddenFolder in (ff for ff in forbiddenFolders if ff==folder["name"]):
            body_of_email += "Using a task within a folder that is not permitted %s \r\n"% forbiddenFolder
            break
tasks = {
    'design': 'later',
    'testing': 'desired',
    'vacation': 'fall'
}

folders = {
    'summer': 'red',
    'fall': 'gold',
    'winter': 'white',
    'spring': 'green'
}

def apply_some_logic(a, b, c, d):
    return '_'.join([a, b, c, d]) if b == c else (a, b, c, d)


if __name__ == '__main__':
    results = (apply_some_logic(a, b, c, d) for a, b in tasks.items() for c, d in folders.items())
    for result in results:
        print(result)


$ python3.6 --version
Python 3.6.4

output:
('design', 'later', 'Summer', 'Red')
('design', 'later', 'Fall', 'Gold')
('design', 'later', 'Winter', 'White')
('design', 'later', 'Spring', 'Green')
('implementation', 'urgent', 'Summer', 'Red')
('implementation', 'urgent', 'Fall', 'Gold')
('implementation', 'urgent', 'Winter', 'White')
('implementation', 'urgent', 'Spring', 'Green')
('testing', 'desired', 'Summer', 'Red')
('testing', 'desired', 'Fall', 'Gold')
('testing', 'desired', 'Winter', 'White')
('testing', 'desired', 'Spring', 'Green')
('vacation', 'Fall', 'Summer', 'Red')
vacation_Fall_Fall_Gold
('vacation', 'Fall', 'Winter', 'White')
('vacation', 'Fall', 'Spring', 'Green')

从最初调查中错综复杂的细节后退一步, 并将注意力放在中的一些“嵌套for循环的替代方案”上 一般情况下,以下各项如何:

for task in (t for t in tasks if entry["item_id"]==t["id"]):
    for folder in (f for f in folders if task["parent_id"]==f["id"]):
        for forbiddenFolder in (ff for ff in forbiddenFolders if ff==folder["name"]):
            body_of_email += "Using a task within a folder that is not permitted %s \r\n"% forbiddenFolder
            break
tasks = {
    'design': 'later',
    'testing': 'desired',
    'vacation': 'fall'
}

folders = {
    'summer': 'red',
    'fall': 'gold',
    'winter': 'white',
    'spring': 'green'
}

def apply_some_logic(a, b, c, d):
    return '_'.join([a, b, c, d]) if b == c else (a, b, c, d)


if __name__ == '__main__':
    results = (apply_some_logic(a, b, c, d) for a, b in tasks.items() for c, d in folders.items())
    for result in results:
        print(result)


$ python3.6 --version
Python 3.6.4

output:
('design', 'later', 'Summer', 'Red')
('design', 'later', 'Fall', 'Gold')
('design', 'later', 'Winter', 'White')
('design', 'later', 'Spring', 'Green')
('implementation', 'urgent', 'Summer', 'Red')
('implementation', 'urgent', 'Fall', 'Gold')
('implementation', 'urgent', 'Winter', 'White')
('implementation', 'urgent', 'Spring', 'Green')
('testing', 'desired', 'Summer', 'Red')
('testing', 'desired', 'Fall', 'Gold')
('testing', 'desired', 'Winter', 'White')
('testing', 'desired', 'Spring', 'Green')
('vacation', 'Fall', 'Summer', 'Red')
vacation_Fall_Fall_Gold
('vacation', 'Fall', 'Winter', 'White')
('vacation', 'Fall', 'Spring', 'Green')

通常情况下,嵌套循环只在您迭代大量内容时才是一个问题——在本例中,您实际上是在搜索一条向下的路径,因此它不会像大多数情况下那样效率低下,因为您很早就失败了。欢迎使用嵌套循环!我把你的问题简化了一点——没有必要在每个问题的结尾说“提前谢谢”。嵌套循环通常只在你迭代大量内容时才是一个问题——在这种情况下,基本上你是在寻找一条向下的路径,所以它不会像在大多数情况下你很早就失败那样效率低下。欢迎使用它!我把你的问题精简了一点-没有必要在每个问题的结尾说“谢谢”。使用文件夹设置\u id
folder\u id=set(f[“id”]表示文件夹中的f)
此外,如果禁止文件夹的顺序不相关,请使用一个集合:
forbiddenFolders=set('folder1',folder2')
,此外,如果禁止文件夹的顺序不相关,请为其使用一个集合:
forbiddenFolders=set('folder1','folder2')
,然后也为操作中的文件夹使用一个集合:
forbiddenFolders=set('folder1','folder2')