如何从重复值列表中获取唯一值集合
我需要处理一个很大的日志文件(平面文件),这个文件里有两列数据(列A和列B)。
这两列里的值是会重复的。我需要找出列A中每个独特的值,然后找出对应的一组列B的值。
这个可以用Unix的命令行来完成吗?还是说需要写一些Perl或Python的脚本?有什么方法可以做到这一点呢?
示例:
xxxA 2
xxxA 1
xxxB 2
XXXC 3
XXXA 3
xxxD 4
输出:
xxxA - 2,1,3
xxxB - 2
xxxC - 3
xxxD - 4
7 个回答
1
你可以使用这个简单的多重映射(multimap):
class MultiMap(object):
values = {}
def __getitem__(self, index):
return self.values[index]
def __setitem__(self, index, value):
if not self.values.has_key(index):
self.values[index] = []
self.values[index].append(value)
def __repr__(self):
return repr(self.values)
看看它是怎么工作的:http://codepad.org/xOOrlbnf
5
这是一个Perl语言的“单行代码”,它被扩展成可以在窗口中完整显示的样子:
$ perl -F -lane '
$hash{ $F[0] }{ $F[1] }++;
} END {
for my $columnA ( keys %hash ) {
print $columnA, " - ", join( ",", keys %$hash{$columnA} ), "\n";
}
'
如果我看到原作者有认真尝试,我会接着解释。
3
我会使用Python的字典,字典的键是A列的值,而字典的值是Python内置的集合类型,用来存放B列的值。
def parse_the_file():
lower = str.lower
split = str.split
with open('f.txt') as f:
d = {}
lines = f.read().split('\n')
for A,B in [split(l) for l in lines]:
try:
d[lower(A)].add(B)
except KeyError:
d[lower(A)] = set(B)
for a in d:
print "%s - %s" % (a,",".join(list(d[a])))
if __name__ == "__main__":
parse_the_file()
使用字典的好处是每个A列的值都有一个唯一的字典键。使用集合的好处是B列的值都是独一无二的,不会重复。
效率小贴士:
- 使用try-catch比用if\else语句来检查初始情况更高效。
- 在循环外部进行字符串函数的评估和赋值比在循环内部直接使用它们更高效。
- 根据文件中新出现的A值和重复出现的A值的比例,你可能会考虑在try-catch语句之前使用
a = lower(A)
。 - 我使用了一个函数,因为在Python中访问局部变量比访问全局变量更高效。
- 这些性能小贴士有些来自这里。
在你的输入示例上测试上面的代码会得到:
xxxd - 4
xxxa - 1,3,2
xxxb - 2
xxxc - 3