我有一个日志文件,我需要从中删除重复的条目。文件中的每一行由逗号分隔的三个部分组成,我们分别称它们为A,B和C.
当且仅当他们的A和C相等时,两个条目是重复的。如果找到重复项,则保留最大B的那个。
真实日志文件有大量行,以下仅作为简化示例:
日志文件(输入):
hostA, 1507300700.0, xyz
hostB, 1507300700.0, abc
hostB, 1507300800.0, xyz
hostA, 1507300800.0, xyz
hostA, 1507300900.0, xyz
删除(输出)重复项后的日志文件:
hostB, 1507300700.0, abc
hostB, 1507300800.0, xyz
hostA, 1507300900.0, xyz
我尝试将文件读入两个列表,然后按照以下方式进行比较:
for i in full_log_list_a:
for j in full_log_list_b:
if i[0] == j[0] and i[2] == j[2] and i[1] > j[1]:
print(', '.join(i[0]), file=open(new_file, 'a'))
我还尝试过其他一些东西,但无论我做什么,它最终会在列表上迭代太多次并创建一堆重复条目,或者它无法找到具有最大B的项目。我知道可能有一个明显的答案,但我被困住了。有人可以指出我正确的方向吗?
答案 0 :(得分:2)
我认为你要找的是dict而不是列表。
当您读取日志文件时,您将向dict添加条目,其中每个条目由一个键(A,C)和一个值B组成。如果一个键已经存在,则将B与映射到该键的值进行比较,并在必要时重新映射密钥(即,如果B大于当前映射到密钥的值)。
示例(对变量a,b和c使用更好的名称):
log_file_entries = {}
with open(log_file, 'r') as f:
for line in f:
a, b_str, c = line.split(', ')
b = int(b_str)
if (a, c) in log_file_entries:
if b < log_file_entries[(a, c)]:
continue
log_file_entries[(a, c)] = b
这是一个循环。由于对dicts的所需操作(通常)在时间上是恒定的,即O(1),因此整体time complexity将为O(n),远优于嵌套循环的O(n²)时间复杂度。< / p>
当你稍后重写文件时,你可以像这样循环遍历dict:
with open(new_file, 'a') as f:
for (a, c), b in log_file_entries.items():
print('{0}, {1}, {2}'.format(a, b, c), file=f)
如果任何代码或术语不正确,我会道歉。我暂时没有触及Python。
(P.S。在您的示例代码中,您使用两个列表,而您可以在两个循环中使用相同的列表。)
<强>更新强>
如果您希望键的值包含日志文件中某一行的每个部分,您可以像这样重写上面的代码:
log_file_entries = {}
with open(log_file, 'r') as f:
for line in f:
a, b_str, c = line.split(', ')
b = int(b_str)
if (a, c) in log_file_entries:
if b < log_file_entries[(a, c)][1]:
continue
log_file_entries[(a, c)] = (a, b, c)
with open(new_file, 'a') as f:
for entry in log_file_entries.values():
print(', '.join(entry), file=f)