如何将带有 if 语句的嵌套 for 循环转换为列表理解?
How can I transform nested for-loops with if-statements into a list comprehension?
我对列表理解完全陌生,我知道如何做一个基本的。但是,如何将这些带有 if 语句的嵌套 for 循环转换为列表理解?
仅供参考:listDicts1
和 listDicts2
是词典列表(不想提供它们,因为它们非常大)。
for d in listDicts1:
for d2 in listDicts2:
if d['name'] in d2['text']:
d['person'].append(d2)
print(d)
我的尝试:
new = [d2 for d in listDicts1 for d in listDicts2 if d['name'] in d2['text']]
我从您在此处构造循环的方式推断了很多,如果您能提供一个最小的示例会更容易。
listDicts1 = [{'name': 'A', 'person': []}, {'name': 'B', 'person': []}]
listDicts2 = [{'text': ['A', 'B']}, {'text': ['B', 'C']}, {'text': ['C', 'A']}]
[d1['person'].append(d2) for d1 in listDicts1 for d2 in listDicts2 if d1['name'] in
d2['text']]
print(listDicts1)
"[{'name': 'A', 'person': [{'text': ['A', 'B']}, {'text': ['C', 'A']}]}, {'name': 'B',
'person': [{'text': ['A', 'B']}, {'text': ['B', 'C']}]}]"
这样做是否是个好主意,还有待商榷,我唯一反对的是它的可读性。
我倾向于同意@Aplet123 的评论,即OP 的初始代码简洁易读。但是有一个 重要的警告:它确实修改了 listDicts1
的指令,这在我的书中是一个很大的禁忌:想象一个毫无戒心的用户(你自己,在三个月内)有一堆口述,将它们放在一个列表中并将其传递给您的函数,只是为了(后来,在调试和挠头的过程中)发现原始口述本身已被偷偷修改到位作为一个方面 -你的功能的影响......(我向你保证,最好的家庭都会发生这种情况)。
因此,如果您希望保持初始指令不变,这样更安全并且恕我直言总是更可取,那么只要需要修改(当您的条件为真时),您就必须生成新的指令.
版本 1:纯粹的理解(但总是会产生新的口述):
listDicts3 = [{
**d,
**{'person': d.get('person', []) + [
d2 for d2 in listDicts2 if d['name'] in d2['text']
]}} for d in listDicts1]
版本 2,首选:只在需要时制作新的字典(其他只是通过引用复制):
persons = [[d2 for d2 in listDicts2 if d['name'] in d2['text']] for d in listDicts1]
listDicts3 = [
{**d, **dict(person=d.get('person', []) + p)} if p else d
for d, p in zip(listDicts1, persons)
]
请注意,如果 person
还不是 d
的成员,则以上两个都以空列表开头。
测试示例:
listDicts1 = [dict(name='fred', person=[]), dict(name='paul', person=[])]
listDicts2 = [dict(text='paul ate an apple'), dict(text='anne reads a book')]
# ... (one of the code snippets above to make listDicts3)
listDicts3
# output:
[{'name': 'fred', 'person': []},
{'name': 'paul', 'person': [{'text': 'paul ate an apple'}]}]
listDicts1
# out (shows it is unchanged)
[{'name': 'fred', 'person': []}, {'name': 'paul', 'person': []}]
# your code, with side-effect
for d in listDicts1:
for d2 in listDicts2:
if d['name'] in d2['text']:
d['person'].append(d2)
print(d)
# out:
{'name': 'fred', 'person': []}
{'name': 'paul', 'person': [{'text': 'paul ate an apple'}]}
# HOWEVER:
listDicts1
# out:
[{'name': 'fred', 'person': []},
{'name': 'paul', 'person': [{'text': 'paul ate an apple'}]}]
注意:您可以避免副作用并保持代码几乎原样:
for d in listDicts1:
d = d.copy()
for d2 in listDicts2:
if d['name'] in d2['text']:
d['person'].append(d2)
print(d)
我对列表理解完全陌生,我知道如何做一个基本的。但是,如何将这些带有 if 语句的嵌套 for 循环转换为列表理解?
仅供参考:listDicts1
和 listDicts2
是词典列表(不想提供它们,因为它们非常大)。
for d in listDicts1:
for d2 in listDicts2:
if d['name'] in d2['text']:
d['person'].append(d2)
print(d)
我的尝试:
new = [d2 for d in listDicts1 for d in listDicts2 if d['name'] in d2['text']]
我从您在此处构造循环的方式推断了很多,如果您能提供一个最小的示例会更容易。
listDicts1 = [{'name': 'A', 'person': []}, {'name': 'B', 'person': []}]
listDicts2 = [{'text': ['A', 'B']}, {'text': ['B', 'C']}, {'text': ['C', 'A']}]
[d1['person'].append(d2) for d1 in listDicts1 for d2 in listDicts2 if d1['name'] in
d2['text']]
print(listDicts1)
"[{'name': 'A', 'person': [{'text': ['A', 'B']}, {'text': ['C', 'A']}]}, {'name': 'B',
'person': [{'text': ['A', 'B']}, {'text': ['B', 'C']}]}]"
这样做是否是个好主意,还有待商榷,我唯一反对的是它的可读性。
我倾向于同意@Aplet123 的评论,即OP 的初始代码简洁易读。但是有一个 重要的警告:它确实修改了 listDicts1
的指令,这在我的书中是一个很大的禁忌:想象一个毫无戒心的用户(你自己,在三个月内)有一堆口述,将它们放在一个列表中并将其传递给您的函数,只是为了(后来,在调试和挠头的过程中)发现原始口述本身已被偷偷修改到位作为一个方面 -你的功能的影响......(我向你保证,最好的家庭都会发生这种情况)。
因此,如果您希望保持初始指令不变,这样更安全并且恕我直言总是更可取,那么只要需要修改(当您的条件为真时),您就必须生成新的指令.
版本 1:纯粹的理解(但总是会产生新的口述):
listDicts3 = [{
**d,
**{'person': d.get('person', []) + [
d2 for d2 in listDicts2 if d['name'] in d2['text']
]}} for d in listDicts1]
版本 2,首选:只在需要时制作新的字典(其他只是通过引用复制):
persons = [[d2 for d2 in listDicts2 if d['name'] in d2['text']] for d in listDicts1]
listDicts3 = [
{**d, **dict(person=d.get('person', []) + p)} if p else d
for d, p in zip(listDicts1, persons)
]
请注意,如果 person
还不是 d
的成员,则以上两个都以空列表开头。
测试示例:
listDicts1 = [dict(name='fred', person=[]), dict(name='paul', person=[])]
listDicts2 = [dict(text='paul ate an apple'), dict(text='anne reads a book')]
# ... (one of the code snippets above to make listDicts3)
listDicts3
# output:
[{'name': 'fred', 'person': []},
{'name': 'paul', 'person': [{'text': 'paul ate an apple'}]}]
listDicts1
# out (shows it is unchanged)
[{'name': 'fred', 'person': []}, {'name': 'paul', 'person': []}]
# your code, with side-effect
for d in listDicts1:
for d2 in listDicts2:
if d['name'] in d2['text']:
d['person'].append(d2)
print(d)
# out:
{'name': 'fred', 'person': []}
{'name': 'paul', 'person': [{'text': 'paul ate an apple'}]}
# HOWEVER:
listDicts1
# out:
[{'name': 'fred', 'person': []},
{'name': 'paul', 'person': [{'text': 'paul ate an apple'}]}]
注意:您可以避免副作用并保持代码几乎原样:
for d in listDicts1:
d = d.copy()
for d2 in listDicts2:
if d['name'] in d2['text']:
d['person'].append(d2)
print(d)