【问题标题】:Count Duplicate URLs, fastest method possible计算重复的 URL,可能的最快方法
【发布时间】:2010-09-20 20:45:51
【问题描述】:

我仍在处理这个庞大的 URL 列表,我收到的所有帮助都很棒。

目前我的列表看起来像这样(虽然有 17000 个 URL):

http://www.example.com/page?CONTENT\_ITEM\_ID=1
http://www.example.com/page?CONTENT\_ITEM\_ID=3
http://www.example.com/page?CONTENT\_ITEM\_ID=2
http://www.example.com/page?CONTENT\_ITEM\_ID=1
http://www.example.com/page?CONTENT\_ITEM\_ID=2
http://www.example.com/page?CONTENT\_ITEM\_ID=3
http://www.example.com/page?CONTENT\_ITEM\_ID=3

我可以用几种方法过滤掉重复项,awk 等没有问题。我真正想做的是取出重复的 URL,但同时计算 URL 中存在的次数使用管道分隔符列出并打印 URL 旁边的计数。处理完列表后应该是这样的:

网址 |数

http://www.example.com/page?CONTENT\_ITEM\_ID=1 | 2
http://www.example.com/page?CONTENT\_ITEM\_ID=2 | 2
http://www.example.com/page?CONTENT\_ITEM\_ID=3 | 3

什么方法是实现这一目标的最快方法?

【问题讨论】:

  • 该用户之前提出的所有问题都是 Python ——我认为这也是 Python。出于这个原因,我把 [python] 放在了这个问题上。
  • 我删除了它,因为它不在问题中,我不知道这个用户只询问了 Python。
  • 我在问一般,任何方法都可以,我有兴趣看到不同的方法,都很好:)
  • 我添加了language-agnostic标签并删除了unix

标签: text-processing


【解决方案1】:

这可能是您无需编写代码即可获得的最快速度。

$ 猫 foo.txt http://www.domain.com/page?CONTENT_ITEM_ID=1 http://www.domain.com/page?CONTENT_ITEM_ID=3 http://www.domain.com/page?CONTENT_ITEM_ID=2 http://www.domain.com/page?CONTENT_ITEM_ID=1 http://www.domain.com/page?CONTENT_ITEM_ID=2 http://www.domain.com/page?CONTENT_ITEM_ID=3 http://www.domain.com/page?CONTENT_ITEM_ID=3 $ 排序 foo.txt |唯一的-c 2 http://www.domain.com/page?CONTENT_ITEM_ID=1 2 http://www.domain.com/page?CONTENT_ITEM_ID=2 3 http://www.domain.com/page?CONTENT_ITEM_ID=3

做了一些测试,速度不是特别快,虽然对于 17k 来说它只需要 1 秒多一点(在加载的 P4 2.8Ghz 机器上)

$ wc -l foo.txt 174955 foo.txt vinko@mithril:~/i3media/2008/product/Pending$ 时间排序 foo.txt |唯一的-c 54482 http://www.domain.com/page?CONTENT_ITEM_ID=1 48212 http://www.domain.com/page?CONTENT_ITEM_ID=2 72261 http://www.domain.com/page?CONTENT_ITEM_ID=3 真正的 0m23.534s 用户 0m16.817s 系统 0m0.084s $ wc -l foo.txt 14955 foo.txt $ 时间排序 foo.txt |唯一的-c 4233 http://www.domain.com/page?CONTENT_ITEM_ID=1 4290 http://www.domain.com/page?CONTENT_ITEM_ID=2 6432 http://www.domain.com/page?CONTENT_ITEM_ID=3 真实0m1.349s 用户 0m1.216s 系统 0m0.012s

虽然 O() 像往常一样赢得了比赛。测试了 S.Lott 的解决方案和

$猫pythoncount.py 从集合导入 defaultdict 我的文件 = 打开(“foo.txt”,“ru”) fq= defaultdict( int ) 对于 myFile 中的 n: fq[n] += 1 对于 fq.items() 中的 n: 打印 "%s|%s" % (n[0].strip(),n[1]) $ wc -l foo.txt 14955 foo.txt $ 时间 python pythoncount.py http://www.domain.com/page?CONTENT_ITEM_ID=2|4290 http://www.domain.com/page?CONTENT_ITEM_ID=1|4233 http://www.domain.com/page?CONTENT_ITEM_ID=3|6432 实际0m0.072s 用户 0m0.028s 系统 0m0.012s $ wc -l foo.txt 1778955 foo.txt $ 时间 python pythoncount.py http://www.domain.com/page?CONTENT_ITEM_ID=2|504762 http://www.domain.com/page?CONTENT_ITEM_ID=1|517557 http://www.domain.com/page?CONTENT_ITEM_ID=3|756636 实际0m2.718s 用户 0m2.440s 系统 0m0.072s

【讨论】:

【解决方案2】:

你会一遍又一遍地这样做吗?如果不是,那么“最快”的实现速度可能是最快的

sort </file/of/urls | uniq --count | awk '{ print $2, " | ", $1}'

(未测试,我不在 UNIX 命令行附近)

【讨论】:

    【解决方案3】:

    在 perl 中

    [免责声明:目前无法测试此代码]

    while (<>) {
        chomp;
        $occurences{$_}++;
    }
    foreach $url (sort keys %occurences) {
        printf "%s|%d\n", $url, $occurences{$url};
    }
    

    【讨论】:

    • 有效。猫 foo.txt | perlcount.pl 。根据我的测试,它比等效的 python 解决方案快一点
    • 它是迄今为止最快的(如“时间”)。它比最接近的竞争对手快 3 倍。 stackoverflow.com/questions/264930/#297512
    【解决方案4】:

    Converting a list of tuples into a dict in python

    本质上,您使用 int 而不是列表做同样的事情。

    这可能比系统排序更快,因为它是 O(n)。但是,它也是 Python,而不是 C。

    from collections import defaultdict
    myFile = open( "urlFile", "ru" )
    fq= defaultdict( int )
    for n in myFile:
        fq[n] += 1
    
    for url, count in fq.iteritems():
        print url.rstrip(), "|", count
    

    在我的小戴尔 D830 上,这可以在 0.015 秒内处理 17000 个 URL。

    【讨论】:

    • 双核。没有后台负载。此外,我运行了几次以获得平均超过 10 次运行:0.015 是最坏的情况,第一次。在那之后,我猜缓存被加载并且它变得更快。平均值为 0.0125。
    • 添加了脚本的打印部分。
    【解决方案5】:

    这是 Python 的另一个版本:

    import fileinput, itertools
    
    urls = sorted(fileinput.input())
    for url, sameurls in itertools.groupby(urls):
        print url.rstrip(), "|", sum(1 for _ in sameurls)
    

    例子:

    $ cat foo.txt
    http://www.domain.com/page?CONTENT_ITEM_ID=1
    http://www.domain.com/page?CONTENT_ITEM_ID=3
    http://www.domain.com/page?CONTENT_ITEM_ID=2
    http://www.domain.com/page?CONTENT_ITEM_ID=1
    http://www.domain.com/page?CONTENT_ITEM_ID=2
    http://www.domain.com/page?CONTENT_ITEM_ID=3
    http://www.domain.com/page?CONTENT_ITEM_ID=3
    
    $ python countuniq.py foo.txt
    http://www.domain.com/page?CONTENT_ITEM_ID=1 | 2
    http://www.domain.com/page?CONTENT_ITEM_ID=2 | 2
    http://www.domain.com/page?CONTENT_ITEM_ID=3 | 3
    

    性能:

    C:\> timethis "sort urls17000.txt|uniq -c"
    ...
    TimeThis :  Elapsed Time :  00:00:00.688
    
    C:\> timethis python countuniq.py urls17000.txt
    ...
    TimeThis :  Elapsed Time :  00:00:00.625
    
    C:\> timethis python slott.py urls17000.txt
    ...
    TimeThis :  Elapsed Time :  00:00:00.562
    
    C:\> timethis perl toolkit.pl urls17000.txt
    ...
    TimeThis :  Elapsed Time :  00:00:00.187
    

    结论:所有解决方案都在 1 秒以内。管道最慢,S.Lott's solution 比上面的 python 版本快,toolkit's perl solution 最快。


    C:\> timethis perl toolkit.pl urls1778955.txt
    ...
    TimeThis :  Elapsed Time :  00:00:17.656
    
    C:\> timethis "sort urls1778955.txt|uniq -c"
    ...
    TimeThis :  Elapsed Time :  00:01:54.234
    
    $ wc urls1778955.txt
    1778955  1778955 81831930 urls1778955.txt
    

    散列胜过对大量网址进行排序。

    【讨论】:

    • 相对距离很大,Perl 的时间是第二快的竞争对手的三分之一。
    猜你喜欢
    • 2013-02-13
    • 2016-02-22
    • 1970-01-01
    • 2013-12-31
    • 1970-01-01
    • 1970-01-01
    • 2016-02-11
    • 2011-12-26
    相关资源
    最近更新 更多