在元组列表中,如果元组[0]是lis中另一个元组[0]的副本,则返回元组[1]

2024-06-16 09:02:46 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个包含两个字符串的元组的列表。
第一个是校验和,第二个是相应文件的名称。
有没有一种快速的方法来搜索重复的校验和并返回相应的文件名?你知道吗

例如:

[("sumstring1","abc.txt"),("sumstring2","def.txt"),("sumstring1","ghi.txt"),("sumstring2","jkl.txt")]
-->
    [("abc.txt","ghi.txt"),("def.txt","jkl.txt")]

我试过制作两个不同的列表,一个是cheksums,另一个是filename。 然后我用collections.Counter找到重复的校验和。使用list.index()我从另一个列表中得到了它们的索引和相应的文件名,如下所示:

csList=["sumstring1","sumstring2","sumstring1","sumstring2"]
fnList=["abc.txt","def.txt","ghi.txt","jkl.txt"]
indexList=[]

multiList=[(k,v) for k,v in collections.Counter(csList).items() if v>1]

(在这种情况下multiList将是[("sumstring1",2),("sumstring2",2)]

for elem in multiList:
    temp=()
    for i in range(elem[1]):
        temp+=(csList.index(elem[0]),)
        csList.remove(elem[0])
    indexList.append(temp)

这给了我一个包含重复文件([(0,2),(1,3)])索引的列表,然后我可以用它来查找文件名。你知道吗

这很管用,但很难看。有没有更简单、更“python”的方法?你知道吗


Tags: intxt列表fordefjkl校验temp
3条回答

你想要的是dictionary。这将为您提供即时查找时间并消除重复键。你知道吗

d = {}
d['sumstring1'] = 'abc.txt'
d.get('sumstring1')
>>> 'abc.txt'
d['sumstring1']
>>> 'abc.txt'

不能添加两次密钥,因此如果添加:

d['sumstring1'] = 'def.txt'

您将用新值替换旧值。你知道吗

要记录多个结果,只需在字典列表中存储一个列表即可:

d['sumstring2'] = ['ghi.txt', 'jkl.txt']

你几乎不想在列表中使用index。在迭代时跟踪您所在的位置;不要试图再次从值中找到您的位置。你知道吗

在本例中,您真正想要的是一个“multidict”,一个将键映射到值集合的字典。在本例中,校验和是对名称集合的校验和。然后,任何映射到一个包含多个名称的集合的校验和,都是一个dup,而这个集合正是您要打印的名称列表,所以这就是所需要的。你知道吗

在Python中,multidict通常表示为一个dict,其值是列表或集合。您可以使用元组,正如您所尝试的那样,它将起作用,但从概念上讲,它们通常表示固定长度、异构的值集合,其中值的索引告诉您有关其含义的信息。这里的长度是任意的。值的同质集合,其中索引没有意义,甚至顺序也没有意义。那是一个集合,不是一个元组。(如果顺序不是无意义的,那么它要么是一个列表,要么是一个OrderedSet。)

例如:

>>> pairs = [("sumstring1","abc.txt"), ("sumstring2","def.txt"),
...          ("sumstring1","ghi.txt"), ("sumstring2","jkl.txt")]
>>> dups = collections.defaultdict(set)
>>> for checksum, name in pairs:
...     dups[checksum].add(name)
>>> dups
defaultdict(<class 'set'>, {'sumstring1': {'ghi.txt', 'abc.txt'}, 'sumstring2': {'def.txt', 'jkl.txt'}})

要消除任何非重复数据:

>>> dups = {checksum: names for checksum, names in dups.items() if len(names) > 1}
>>> dups
{'sumstring1': {'abc.txt', 'ghi.txt'}, 'sumstring2': {'def.txt', 'jkl.txt'}}

(当然,在您的示例中我们没有任何非重复,所以这不是很令人兴奋)。你知道吗

如果您不关心校验和,只需要一个集合列表:

>>> dups = list(dups.values())

如果你真的因为某种原因想要元组而不是集合:

>>> dups = [tuple(names) for names in dups.values()]
>>> dups
[('ghi.txt', 'abc.txt'), ('def.txt', 'jkl.txt')]

你可以用字典。你知道吗

tuples = [("sumstring1","abc.txt"),("sumstring2","def.txt"),("sumstring1","ghi.txt"),("sumstring2","jkl.txt")]

lookup = {}
for checksum, filename in tuples:
    lookup.setdefault(checksum, []).append(filename)

for checksum, filenames in lookup.items():
    if len(filenames) >= 2:
        print(checksum, filenames)

输出为

sumstring1 ['abc.txt', 'ghi.txt']
sumstring2 ['def.txt', 'jkl.txt']

相关问题 更多 >