推荐学习书目
› Learn Python the Hard Way
Python Sites
› PyPI - Python Package Index
› http://diveintopython.org/toc/index.html
› Pocoo
值得关注的项目
› PyPy
› Celery
› Jinja2
› Read the Docs
› gevent
› pyenv
› virtualenv
› Stackless Python
› Beautiful Soup
› 结巴中文分词
› Green Unicorn
› Sentry
› Shovel
› Pyflakes
› pytest
Python 编程
› pep8 Checker
Styles
› PEP 8
› Google Python Style Guide
› Code Style from The Hitchhiker's Guide
daiqiangbudainiu
V2EX  ›  Python

如果有 33W 行文字,去重应该怎么写呢?

  •  
  •   daiqiangbudainiu · Dec 17, 2017 · 7530 views
    This topic created in 3254 days ago, the information mentioned may be changed or developed.

    比如有个 txt 文本,一共有 33W 行文字,以行作为单位,去重,我应该怎么写效率会比较高呢?

    我目前用的普通的方法,发现耗时比较长

    我列出我目前的方法

        with open('/Users/lizhao/Downloads/aboutchinese.dict.yaml') as f:
    
            for i in f.readlines():
                if i == '\n':
                    continue
                if i not in oldList:
                    oldList.append(i)
    
        with open('tmp.txt','w') as g:
            g.writelines(oldList)
    

    代码渣,请轻喷

    44 replies  •  2017-12-20 21:07:00 +08:00
    l00t
    l00t
    Dec 17, 2017
    1
    为啥不用 dict
    realpg
    realpg
    Dec 17, 2017❤️1
    2
    33 万行 这么点数据还考虑啥性能……
    wspsxing
    wspsxing
    Dec 17, 2017
    3
    hash
    ihciah
    ihciah
    Dec 17, 2017 via iPhone
    4
    list 查找是线性的似乎…换成 dict 或者 set 会好
    fy
    fy
    Dec 17, 2017
    5
    蛐蛐 33w 行,pandas 读入,drop_duplicates,导出,收工。
    vimiix
    vimiix
    Dec 17, 2017
    6
    我的话,可能会先考虑用集合 set,下面是伪代码思路:
    values = set()
    vals_len = 0

    dest_file = open('dest_file', 'w')
    with open txt:
    for line in readlines():
    val = hash(line)
    vals_len = len(values)
    values.add(val) #主要在这一步借助 set 的不重复特性,判断集合长度是否增长
    if len(values) == vals_len+1:
    dest_file.write(line)
    dest.file.close()

    仅供参考,没试验过。
    Guaidaodl
    Guaidaodl
    Dec 17, 2017
    7
    list 的查找是 O(n) 的吧,整个复杂度是 O(n^2)。去重的时候不要用 list, 换成 set 就好了。
    em70
    em70
    Dec 17, 2017❤️1
    8
    直接 EmEditor 打开 TXT,工具->插件->删除重复行,搞定
    rrfeng
    rrfeng
    Dec 17, 2017❤️11
    9
    这个题我最喜欢了:

    awk '!a[$0]++' file.txt
    ytterbium
    ytterbium
    Dec 17, 2017 via Android
    10
    这么小数据量,hash, map 都行啊。linux 的话就直接 sort -u,虽然不是最快的,不过简单省心。
    ytterbium
    ytterbium
    Dec 17, 2017 via Android
    11
    @ytterbium 之前做 nlp 数据预处理去重过 5 亿多行的数据,偷懒用的 sort -u,多线程 1 天不到也就跑完了。30 几万行几秒的事。
    param
    param
    Dec 17, 2017 via Android
    12
    转成 set 再转成 list 不知道行不行
    ytterbium
    ytterbium
    Dec 17, 2017 via Android
    13
    @ytterbium 50 亿
    param
    param
    Dec 17, 2017 via Android
    14
    list(set(open('/Users/lizhao/Downloads/aboutchinese.dict.yaml'))) 这样子?不知道性能如何。
    cljnnn
    cljnnn
    Dec 17, 2017 via Android
    15
    用 set,set 自带去重
    ioven
    ioven
    Dec 17, 2017
    16
    如果对流程没太多需要直接用 awk 更简单
    swulling
    swulling
    Dec 17, 2017 via iPhone
    17
    awk dict
    wweir
    wweir
    Dec 17, 2017 via iPhone
    18
    除了 hash,还可以考虑用排序的方法来做
    如果 33w 仅仅是代表大(内存不允许)的话,还可以考虑利用一些磁盘排序的算法
    secsilm
    secsilm
    Dec 17, 2017 via Android
    19
    这也不大吧
    cxbig
    cxbig
    Dec 17, 2017
    20
    sort -u dict.yml
    awk '!a[$0]++' dict.yml
    ceclinux
    ceclinux
    Dec 17, 2017 via Android
    21
    要是对结果没有顺序要求的,不要想太多,直接 sort 然后 uniq 即可
    fyibmsd
    fyibmsd
    Dec 17, 2017
    22
    cat old | uniq | tee new
    artandlol
    artandlol
    Dec 17, 2017❤️3
    23
    一个 uniq 也能发一贴
    root@x:~# cat test
    247
    214
    209
    228
    216
    216
    root@x:~# cat test|uniq
    247
    214
    209
    228
    216
    root@x:~# cat test|sort -u
    209
    214
    216
    228
    247
    root@x:~# cat test|awk '!a[$0]++'
    247
    214
    209
    228
    216
    ericls
    ericls
    Dec 17, 2017❤️1
    24
    from collections import OrderedDict
    '\n'.join(OrderedDict.fromkeys(string.splitlines()))
    selfAccomplish
    selfAccomplish
    Dec 17, 2017 via Android
    25
    如果楼主的数据是在 window 下面呢,没有 linux 的机子或者数据量大拷不进 linux 的虚拟机。
    cdwyd
    cdwyd
    Dec 17, 2017 via Android
    26
    list(set(f.readlines()))
    takeoffyoung
    takeoffyoung
    Dec 17, 2017
    27
    cat xxx.txt | sort | uniq 这样??
    msg7086
    msg7086
    Dec 17, 2017
    28
    @selfAccomplish 那就在 Windows 下用 awk 啊。
    eycfsjd
    eycfsjd
    Dec 17, 2017
    29
    1、for i in f.readlines() 改成 for i in f: 是不是更好;
    2、查重用 dict 性能好,如果每一行都比较长 建议把 line 换算一下再 put 到 dict 中,要保证顺序就 orderdict
    young6
    young6
    Dec 17, 2017 via Android
    30
    要是对行顺序没要求,用 cat,sort,uniq 吧,还写啥代码啊。要是行顺序要求不变,python 有有序字典
    leavic
    leavic
    Dec 17, 2017
    31
    有序字典吧,set 虽然可以去重,但你恢复的时候就无序了。
    wizardoz
    wizardoz
    Dec 17, 2017
    32
    dict 可破,用文本当 key,用行号当 value
    dict 在判断 in 的时候效率应该吊打 list。
    jyf007
    jyf007
    Dec 17, 2017
    33
    @msg7086
    @artandlol
    @young6
    @selfAccomplish
    @swulling
    @ioven
    @rrfeng

    别忘了用这个 https://frippery.org/busybox/
    ,开一个批处理写成 busybox ash 就有坠吼的环境了,(其实没什么大功能)
    我原来写了一个在 windows 处理 netstat 输出的就是这么骚操作.
    artandlol
    artandlol
    Dec 17, 2017 via iPhone
    34
    @jyf007
    cmder
    +gow
    或者用在线 docker-ce 再通过用 websocket 映射到浏览器
    估计你要百度一晚上了
    jyf007
    jyf007
    Dec 17, 2017
    35
    @artandlol 说起来 unix 的好还是只能体现在 busybox 上了,其他不能算是原始的 unix 了
    我当时是直接操作 cmd 的窗口就这 vi 写脚本,或者开记事本搞,
    完整的 msys2 我装完有 45G 这么大,不够轻盈,
    我觉得安利 unix 必须提 busybox 和 dropbear.
    daiqiangbudainiu
    daiqiangbudainiu
    OP
    Dec 17, 2017
    36
    @wizardoz

    能给个示例吗?我不知道该怎么用 dict 去重
    ipwx
    ipwx
    Dec 17, 2017
    37
    24L 是 Python 最优雅的解决方案。
    Lpl
    Lpl
    Dec 17, 2017
    38
    vim 文件

    然后 :sort u
    会先排序然后取相同行第一行
    lylijincheng
    lylijincheng
    Dec 18, 2017
    39
    ```
    Array.from(new Set(longlongtext.split(''))).join('')
    ```
    wizardoz
    wizardoz
    Dec 18, 2017
    40
    @warcraft1236 把你的 list 换成 dict 就可以了!

    buffer = {}
    sort_key = 0
    with open('file.txt', 'r') as fp:
    for line in fp.readlines():
    if line not in buffer:
    sort_key += 1
    buffer[line] = sort_key


    # 完了用 sort_key 排序,保持原来顺序
    ...
    daiqiangbudainiu
    daiqiangbudainiu
    OP
    Dec 18, 2017
    41
    @wizardoz
    多谢,不过再问一个基础的问题,怎么根据 dict 的 values 排序写入文件呢?
    araraloren
    araraloren
    Dec 18, 2017
    42
    .say for f.lines.unique(:with(&[eqv])) (in Perl6, f is IO::Handle)
    wizardoz
    wizardoz
    Dec 18, 2017
    43
    @warcraft1236
    # 排序并丢弃行号信息,得到的是按照原本顺序的文本数据
    sorted_lines = sorted([item[0] for item in buffer.items()], cmp=lambda a, b: a[1] - b[1])

    # 输出
    with open("output.txt", "w") as fp:
    for line in sorted_lines:
    print(line, file=fp)
    shawndev
    shawndev
    Dec 20, 2017
    44
    cat file | uniq
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Privacy   ·   Solana   ·   951 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 160ms · UTC 22:15 · PVG 06:15 · LAX 14:15 · JFK 17:15
    ♥ Do have faith in what you're doing.