我正在处理包含由行分隔的数据的大型文本文件(~20MB)。 大多数数据条目都是重复的,我想删除这些重复项,只保留一份副本。
此外,为了使问题稍微复杂一些,重复一些条目并附加额外的信息。在这种情况下,我需要保留包含额外信息的条目并删除旧版本。
e.g。 我需要离开这个:
BOB 123 1DB JIM 456 3DB AX DAVE 789 1DB BOB 123 1DB JIM 456 3DB AX DAVE 789 1DB BOB 123 1DB EXTRA BITS对此:
JIM 456 3DB AX DAVE 789 1DB BOB 123 1DB EXTRA BITSNB。最后的命令并不重要。
有效的方法是什么?
我可以使用awk,python或任何标准的linux命令行工具。
感谢。
答案 0 :(得分:12)
以下内容(在Python中):
prev = None
for line in sorted(open('file')):
line = line.strip()
if prev is not None and not line.startswith(prev):
print prev
prev = line
if prev is not None:
print prev
如果您发现内存使用存在问题,可以使用Unix sort
(disk-based)将排序作为预处理步骤进行排序,并更改脚本以使其无法读取将整个文件存入内存。
答案 1 :(得分:3)
awk '{x[$1 " " $2 " " $3] = $0} END {for (y in x) print x[y]}'
如果您需要指定不同文件的列数:
awk -v ncols=3 '
{
key = "";
for (i=1; i<=ncols; i++) {key = key FS $i}
if (length($0) > length(x[key])) {x[key] = $0}
}
END {for (y in x) print y "\t" x[y]}
'
答案 2 :(得分:2)
这个或轻微的变体应该:
finalData = {}
for line in input:
parts = line.split()
key,extra = tuple(parts[0:3]),parts[3:]
if key not in finalData or extra:
finalData[key] = extra
pprint(finalData)
输出:
{('BOB', '123', '1DB'): ['EXTRA', 'BITS'],
('DAVE', '789', '1DB'): [],
('JIM', '456', '3DB'): ['AX']}
答案 3 :(得分:2)
glenn jackman的答案的这种变化应该有效,无论有多余位线的位置如何:
awk '{idx = $1 " " $2 " " $3; if (length($0) > length(x[idx])) x[idx] = $0} END {for (idx in x) print x[idx]}' inputfile
或者
awk -v ncols=3 '
{
key = "";
for (i=1; i<=ncols; i++) {key = key FS $i}
if (length($0) > length(x[key])) x[key] = $0
}
END {for (y in x) print x[y]}
' inputfile
答案 4 :(得分:1)
你必须定义一个函数来将你的行分成重要的位和额外的位,然后你可以这样做:
def split_extra(s):
"""Return a pair, the important bits and the extra bits."""
return blah blah blah
data = {}
for line in open('file'):
impt, extra = split_extra(line)
existing = data.setdefault(impt, extra)
if len(extra) > len(existing):
data[impt] = extra
out = open('newfile', 'w')
for impt, extra in data.iteritems():
out.write(impt + extra)
答案 5 :(得分:1)
由于您需要额外的位,最快的方法是创建一组唯一的条目(排序-u会这样做),然后您必须将每个条目相互比较,例如:
if x.startswith(y) and not y.startswith(x)
然后离开x并丢弃y。
答案 6 :(得分:1)
如果您有perl并且只想保留最后一个条目:
cat file.txt | perl -ne 'BEGIN{%k={}} @_ = split(/ /);$kw = shift(@_); $kws{$kw} = "@_"; END{ foreach(sort keys %kws){ print "$_ $kws{$_}";} }' > file.new.txt
答案 7 :(得分:1)
函数find_unique_lines
适用于文件对象或字符串列表。
import itertools
def split_line(s):
parts = s.strip().split(' ')
return " ".join(parts[:3]), parts[3:], s
def find_unique_lines(f):
result = {}
for key, data, line in itertools.imap(split_line, f):
if data or key not in result:
result[key] = line
return result.itervalues()
test = """BOB 123 1DB
JIM 456 3DB AX
DAVE 789 1DB
BOB 123 1DB
JIM 456 3DB AX
DAVE 789 1DB
BOB 123 1DB EXTRA BITS""".split('\n')
for line in find_unique_lines(test):
print line
BOB 123 1DB EXTRA BITS JIM 456 3DB AX DAVE 789 1DB