-5

我有一个包含数百万个这样的向量的文本文件:-

V1
V1
V1
V3
V4
V1
V1

注意:- 订单很重要。在上面的输出文件中,我数了第一个向量 3 次。在第 5 行之后重复相同的模式两次。计数应该不同。

我想计算每条向量行重复多少次并将其添加到输出文本文件中,如下所示:-

在上述 7 个向量中,前 3 行相同,其余 2 行不同,最后一行相同。所以输出应该是这样的:-

V1 count 3
V3
V4
V1 count 2

虽然,第一个和最后一个模式相同,但它们的计数不同,因为它们的顺序不同。

我可以使用pythonor perl。我知道行(向量)的最大长度,但是如何将每一行(向量)与其他行(向量)进行比较。请帮忙

4

7 回答 7

4
perl -nle'
   if ($c && $_ ne $last) {
      print $c > 1 ? "$last repeat$c;" : "$last;";
      $c = 0;
   }

   $last = $_;
   ++$c;

   END {
      if ($c) {
         print $c > 1 ? "$last repeat$c;" : "$last;";
      }
   }
' file

(您可以将所有内容放在一行中,也可以保持原样。)

输出:

V1 repeat3
V3
V4
V1 repeat2

这个解决方案是平均 O(N) CPU 和 O(1) 内存。它和inspectorG4dget 是七个现有答案中仅有的两个,它们以您要求的格式和顺序提供输出。

于 2012-10-16T18:22:22.307 回答
2

只需在命令提示符下运行它

sort text.txt | uniq -c > output.txt

如果要保留排序,请删除排序(仅计算连续的唯一行)

uniq -c text.txt > output.txt

或者这将提供所需的精确输出(ikegami 建议的解决方案)

uniq -c text.txt \
| perl -ple's/^\s*(\d+) //; $_ .= " repeat$1" if $1 > 1; \
> output.txt
于 2012-10-16T18:16:03.357 回答
1

如果顺序无关紧要

如果您真的想在 python 中执行此操作(与sort filepath | uniq -cJean 建议的相反),那么我会这样做:

import collections
with open('path/to/file') as f:
    counts = collections.Counter(f)
    outfile = open('path/to/outfile', 'w')
    for line,occ in counts.iteritems():
        outfile.write("%s repeat %d\n" %(line.strip(), occ))
    outfile.close()

如果订单很重要

如果顺序很重要(如果条目i出现在j输入文件中的条目之前,那么条目i必须出现在j输出文件中的条目之前),那么您需要的是修改后的行程编码器。但是请注意,如果您有以下输入文件:

v1
v1
v1
v2
v2
v3
v1

然后,您的输出文件将如下所示:

v1 repeat 3
v2 repeat 2
v3
v1

with open('infilepath') as infile:
    outfile = open('outfilepath', 'w')
    curr = infile.readline().strip()
    count = 1
    for line in infile:
        if line.strip() == curr:
            count += 1
        else:
            outfile.write(curr)
            if count-1:
                outfile.write(" repeat %d\n" %count)
            else:
                outfile.write("\n")
            curr = line.strip()
            count = 1
    outfile.write(curr)
    if count-1:
        outfile.write(" repeat %d\n" %count)
    outfile.close()

当然,uniq -c infilepath > outfilepath也会这样做

希望这可以帮助

于 2012-10-16T18:21:51.500 回答
0

如果这一切都适合记忆,那么你可以这样做:

from collections import Counter

with open('vectors') as fin:
    counts = Counter(fin)

或者,如果很大,那么您可以使用 sqlite3:

import sqlite3

db = sqlite3.conncet('/some/path/some/file.db')
db.execute('create table vector (vector)')
with open('vectors.txt') as fin:
    db.executemany('insert into vector values(?)', fin)
    db.commit()

for row in db.execute('select vector, count(*) as freq from vector group by vector'):
    print row # do something suitable here

如果向量总是连续的:

from itertools import groupby
with open('vector') as fin:
    for vector, vals in groupby(fin):
        print '{} {}repeat'.format(vector, sum(1 for _ in vals))
于 2012-10-16T18:22:37.757 回答
0

假设 python 2.7,一个内存密集度较低的解决方案

from collections import Counter
with open("some_file.txt") as f:
    cnt = Counter(f)
    print cnt
于 2012-10-16T18:22:49.110 回答
0
vectors = {}
for vector in open("vect.txt").readlines():
    vectors[vector] = vectors.setdefault(vector, 0) + 1
print vectors
于 2012-10-16T18:23:33.190 回答
0

我不认为你可以在少于 O(n^2) 的时间内做到这一点......(我可能是错的)

一种方法是(在python中)

with open("some_file_with_vectors") as f:
          data = f.read()

counts  = dict([(line,data.count(line)) for line in data.splitlines()])
print counts
#if you want to save to a file
with open("output.txt") as f:
   for key in counts:
       print >> f, key ,"=",counts[key]
于 2012-10-16T18:15:54.097 回答