列表理解与自我引用的配合[重复]

问题描述 投票:0回答:3

我正在检索 (

name
,
id
) 对的列表,并且我需要确保
name
没有重复项,无论
id
如何。

# Sample data
filesID = [{'name': 'file1', 'id': '353'}, {'name': 'file2', 'id': '154'},
           {'name': 'file3', 'id': '1874'}, {'name': 'file1', 'id': '14'}]

我设法通过嵌套循环获得所需的输出:

uniqueFilesIDLoops = []
for pair in filesID:
    found = False
    for d in uniqueFilesIDLoops:
        if d['name'] == pair['name']:
            found = True
    if not found:
        uniqueFilesIDLoops.append(pair)

但我无法让它与列表理解一起工作。这是我迄今为止尝试过的:

uniqueFilesIDComprehension = []
uniqueFilesIDComprehension = [
    pair for pair in filesID if pair['name'] not in [
        d['name'] for d in uniqueFilesIDComprehension
    ]
]

输出:

# Original data
[{'name': 'file1', 'id': '353'}, {'name': 'file2', 'id': '154'},
 {'name': 'file3', 'id': '1874'}, {'name': 'file1', 'id': '14'}]

# Data obtained with list comprehension
[{'name': 'file1', 'id': '353'}, {'name': 'file2', 'id': '154'},
 {'name': 'file3', 'id': '1874'}, {'name': 'file1', 'id': '14'}]

# Data obtained with loops (and desired output)
[{'name': 'file1', 'id': '353'}, {'name': 'file2', 'id': '154'},
 {'name': 'file3', 'id': '1874'}]

我在想,也许列表理解中对

uniqueFilesIDComprehension
的调用在每次迭代时都没有更新,因此使用
[]
而没有找到相应的值。

python list for-loop list-comprehension
3个回答
1
投票

您无法在创建列表推导式的过程中访问其内容,因为只有在其值完全求值后才会将其分配给任何内容。

删除重复项的最简单方法是:

list({el['name'] : el for el in filesID}.values())
- 这将根据每个元素的名称创建一个字典,因此每次遇到重复的名称时,它都会用新元素覆盖它。创建字典后,您需要做的就是获取值并将其转换为
list
。 如果您想保留每个名称的第一个元素,而不是最后一个元素,您可以通过在 for 循环中创建字典来实现:

out = {}
for el in filesID:
    if el['name'] not in out:
        out[el['name']] = el

最后,在实施任何这些解决方案时要考虑的一件事 - 因为您不关心

id
部分,您真的需要提取它吗?

我会问自己这是否也是一个有效的选择。

out = {el['name'] for el in filesID}
print(out)

输出:

{'file1', 'file3', 'file2'}


1
投票

我会坚持你原来的循环,但请注意它可以变得更干净一些。也就是说,您不需要名为

found
的标志。

uniqueFilesIDLoops = []
for pair in filesID:
    for d in uniqueFilesIDLoops:
        if d['name'] == pair['name']:
            break
    else:
        uniqueFilesIDLoops.append(pair)

您还可以使用辅助 set 来简化检测重复名称(因为它们是

str
值,因此可散列)。

seen = set()
uniqueFilesIDLoops = []
for pair in filesID:
    if (name := pair['name']) not in seen:
        seen.add(name)
        uniqueFilesIDLoops.append(pair)

因为我们现在已经将结果与执行查找的数据结构解耦,所以可以通过编写一个表达式将上面的内容转换为列表理解,当名称不在集合中时,该表达式都返回 True 并且将名称添加到该集。一些不确定的事情,比如

seen = set() uniqueFilesIDLoops = [pair for pair in filesID if (pair['name'] not in seen and (seen.add(pair['name']) or True))]

seen.add

始终返回
None
,这是一个错误值,因此
seen.add(...) or True
始终是
True
。)


0
投票
列表推导式用于

创建新列表,因此原始列表永远不会更新; 赋值使变量引用新创建的列表。

© www.soinside.com 2019 - 2024. All rights reserved.