我有一个由包含2个字符串的元组组成的列表 第一个是校验和,第二个是相应文件的名称 有没有快速的方法来搜索重复的校验和并返回相应的文件名?
例如:
[("sumstring1","abc.txt"),("sumstring2","def.txt"),("sumstring1","ghi.txt"),("sumstring2","jkl.txt")]
-->
[("abc.txt","ghi.txt"),("def.txt","jkl.txt")]
我尝试制作两个不同的列表,一个是cheksums,另一个是文件名。
然后我使用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"这样做的方法?
答案 0 :(得分:1)
您几乎不想在列表中使用index
。迭代时跟踪你的位置;不要试图从价值中再次找到你的位置。
在这种情况下,你真正想要的是一个" multidict",一个将键映射到值集合的字典。在这种情况下,校验和到名称集合。然后,任何映射到一组多于一个名称的校验和,它都是双重的,并且该集合恰好是您要打印出来的名称列表,所以它只需要。
在Python中,multidict通常表示为dict,其值为列表或集合。您可以使用元组,正如您尝试的那样,它将工作 - 但从概念上讲,它们通常代表固定长度的异构值集合,其中a的索引值告诉你它的含义。我们这里有任意长度。同质的价值集合,其中指数毫无意义,甚至订单也毫无意义。这是一套,而不是一个元组。 (如果订单没有意义,那么它可以是列表,也可以是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')]
答案 1 :(得分:0)
你想要的是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']
答案 2 :(得分:0)
你可以使用字典。
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']