0

ファイルから読み取った禁止フォルダーのリストを比較しようとしています。ただし、タスクにフォルダーの親 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

このコードでは、ネストされた 3 つのforループが使用されているため、処理が遅くなる可能性があります。これをより効率的にすることはできますか?

4

4 に答える 4

3

コードの行数を減らして、次のように理解しやすくすることができます。

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" )
于 2012-06-15T23:00:37.990 に答える
2

ここで実行しようとしているのは、IDに基づいてアイテム(タスク、フォルダー)を検索することです。Pythonの辞書は、これを行う簡単な方法を提供します。検索を数回実行する場合(たとえば、同じIDを持つタスクが多数ある場合、または関数を数回実行する場合)にのみ保存します。

さらに、forbiddenFoldersの場合、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_dict[id]なタスクです。task['id'] == idセットではこれは許可されていませんが、で存在を確認できますfolder in forbidden_folders_set

(これらの各dict(...)操作は、上記のforループのいずれかを実行するよりも時間がかかる場合がありますが、将来のルックアップを高速化するための投資であることに注意してください。)

if entry['item_id'] in tasks_dict:
    task = tasks_dict[entry['item_id']]
    if task['parent_id'] in folders_dict:
        folder = folders_dict[task['parent_id']]
        if folder in forbidden_folders_set:
            body_of_email += ...

上記のx in yおよび..._dict[x]操作は非常に効率的です。

于 2012-06-15T23:11:17.040 に答える
1

元のデータ構造を保持できる方法は次のとおりです。

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

これは、非常にメモリ効率が高く、速度を維持するジェネレーターx for x in range(y) if conditionと、フォームの条件付き for ループを利用します。両方見てみることをお勧めします。

于 2012-06-15T23:55:03.973 に答える