Regex/Algorithm 查找文件中 'n' 重复的行
Regex/Algorithm to find 'n' repeated lines in a file
我正在寻找 this 的高级版本。
基本上,如果我有一个包含文本的文件:
abc
ghi
fed
jkl
abc
ghi
fed
我希望输出为:(n=3
)
Duplicated Lines
abc
ghi
fed
Times = 2
一种方法是根据你的 n
拆分你的文本,然后计算你的元素的数量,所有这些都取决于这个计数你可以使用一些使用哈希-table 的数据结构,比如字典python 这对于此类任务非常有效。
任务是创建一个使键保持唯一的字典,然后遍历拆分文本列表并在每次看到重复项时增加每个项目的计数。
最后你会得到一个包含独特项目的字典,这些项目被视为字典的值。
一些像 python 这样的语言提供了很好的工具,例如 Counter
用于计算可迭代对象中的元素和 islice
用于切片和可迭代的 returns 生成器并且非常好对长迭代有效:
>>> from collections import Counter
>>> from itertools import islice
>>> s="""abc
... ghi
... fed
... jkl
... abc
... ghi
... fed"""
>>> sp=s.split()
>>> Counter('\n'.join(islice(sp,i,i+3)) for i in range(len(sp)))
Counter({'abc\nghi\nfed': 2, 'fed': 1, 'jkl\nabc\nghi': 1, 'ghi\nfed': 1, 'fed\njkl\nabc': 1, 'ghi\nfed\njkl': 1})
或者您可以自定义:
>>> a=['\n'.join(sp[i:i+3] for i in range(len(sp))]
>>> a
['abc\nghi\nfed', 'ghi\nfed\njkl', 'fed\njkl\nabc', 'jkl\nabc\nghi', 'abc\nghi\nfed', 'ghi\nfed', 'fed']
>>> d={}
>>> for i in a:
... if i in d:
... d[i]+=1
... else :
... d[i]=1
...
>>> d
{'fed': 1, 'abc\nghi\nfed': 2, 'jkl\nabc\nghi': 1, 'ghi\nfed': 1, 'fed\njkl\nabc': 1, 'ghi\nfed\njkl': 1}
>>>
所以,像这样(在 perl 中):
#!/usr/bin/perl
use strict;
use warnings;
my %seen;
my @order;
while ( my $line = <DATA> ) {
chomp ( $line );
push ( @order, $line ) unless $seen{$line}++;
}
foreach my $element ( @order ) {
print "$element, $seen{$element}\n" if $seen{$element} > 1;
}
__DATA__
abc
ghi
fed
jkl
abc
ghi
fed
这可以通过以下方式变成更短的代码段:
perl -e 'while ( <> ) { push ( @order, $_ ) unless $seen{$_}++; } for (@order) {print if $seen{$_} > 1}' myfile
我正在寻找 this 的高级版本。
基本上,如果我有一个包含文本的文件:
abc
ghi
fed
jkl
abc
ghi
fed
我希望输出为:(n=3
)
Duplicated Lines
abc
ghi
fed
Times = 2
一种方法是根据你的 n
拆分你的文本,然后计算你的元素的数量,所有这些都取决于这个计数你可以使用一些使用哈希-table 的数据结构,比如字典python 这对于此类任务非常有效。
任务是创建一个使键保持唯一的字典,然后遍历拆分文本列表并在每次看到重复项时增加每个项目的计数。
最后你会得到一个包含独特项目的字典,这些项目被视为字典的值。
一些像 python 这样的语言提供了很好的工具,例如 Counter
用于计算可迭代对象中的元素和 islice
用于切片和可迭代的 returns 生成器并且非常好对长迭代有效:
>>> from collections import Counter
>>> from itertools import islice
>>> s="""abc
... ghi
... fed
... jkl
... abc
... ghi
... fed"""
>>> sp=s.split()
>>> Counter('\n'.join(islice(sp,i,i+3)) for i in range(len(sp)))
Counter({'abc\nghi\nfed': 2, 'fed': 1, 'jkl\nabc\nghi': 1, 'ghi\nfed': 1, 'fed\njkl\nabc': 1, 'ghi\nfed\njkl': 1})
或者您可以自定义:
>>> a=['\n'.join(sp[i:i+3] for i in range(len(sp))]
>>> a
['abc\nghi\nfed', 'ghi\nfed\njkl', 'fed\njkl\nabc', 'jkl\nabc\nghi', 'abc\nghi\nfed', 'ghi\nfed', 'fed']
>>> d={}
>>> for i in a:
... if i in d:
... d[i]+=1
... else :
... d[i]=1
...
>>> d
{'fed': 1, 'abc\nghi\nfed': 2, 'jkl\nabc\nghi': 1, 'ghi\nfed': 1, 'fed\njkl\nabc': 1, 'ghi\nfed\njkl': 1}
>>>
所以,像这样(在 perl 中):
#!/usr/bin/perl
use strict;
use warnings;
my %seen;
my @order;
while ( my $line = <DATA> ) {
chomp ( $line );
push ( @order, $line ) unless $seen{$line}++;
}
foreach my $element ( @order ) {
print "$element, $seen{$element}\n" if $seen{$element} > 1;
}
__DATA__
abc
ghi
fed
jkl
abc
ghi
fed
这可以通过以下方式变成更短的代码段:
perl -e 'while ( <> ) { push ( @order, $_ ) unless $seen{$_}++; } for (@order) {print if $seen{$_} > 1}' myfile