比如有个 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)
代码渣,请轻喷
1
l00t 2017-12-17 00:25:37 +08:00
为啥不用 dict
|
2
realpg 2017-12-17 00:47:29 +08:00 1
33 万行 这么点数据还考虑啥性能……
|
3
wspsxing 2017-12-17 00:48:05 +08:00
hash
|
4
ihciah 2017-12-17 00:48:19 +08:00 via iPhone
list 查找是线性的似乎…换成 dict 或者 set 会好
|
5
fy 2017-12-17 00:55:19 +08:00
蛐蛐 33w 行,pandas 读入,drop_duplicates,导出,收工。
|
6
vimiix 2017-12-17 00:57:25 +08:00
我的话,可能会先考虑用集合 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() 仅供参考,没试验过。 |
7
Guaidaodl 2017-12-17 01:12:59 +08:00
list 的查找是 O(n) 的吧,整个复杂度是 O(n^2)。去重的时候不要用 list, 换成 set 就好了。
|
8
em70 2017-12-17 01:15:02 +08:00 1
直接 EmEditor 打开 TXT,工具->插件->删除重复行,搞定
|
9
rrfeng 2017-12-17 01:32:45 +08:00 11
这个题我最喜欢了:
awk '!a[$0]++' file.txt |
10
ytterbium 2017-12-17 03:46:04 +08:00 via Android
这么小数据量,hash, map 都行啊。linux 的话就直接 sort -u,虽然不是最快的,不过简单省心。
|
11
ytterbium 2017-12-17 03:52:11 +08:00 via Android
@ytterbium 之前做 nlp 数据预处理去重过 5 亿多行的数据,偷懒用的 sort -u,多线程 1 天不到也就跑完了。30 几万行几秒的事。
|
12
param 2017-12-17 03:53:15 +08:00 via Android
转成 set 再转成 list 不知道行不行
|
14
param 2017-12-17 03:57:47 +08:00 via Android
list(set(open('/Users/lizhao/Downloads/aboutchinese.dict.yaml'))) 这样子?不知道性能如何。
|
15
cljnnn 2017-12-17 05:56:29 +08:00 via Android
用 set,set 自带去重
|
16
ioven 2017-12-17 08:01:46 +08:00
如果对流程没太多需要直接用 awk 更简单
|
17
swulling 2017-12-17 08:27:26 +08:00 via iPhone
awk dict
|
18
wweir 2017-12-17 08:28:21 +08:00 via iPhone
除了 hash,还可以考虑用排序的方法来做
如果 33w 仅仅是代表大(内存不允许)的话,还可以考虑利用一些磁盘排序的算法 |
19
secsilm 2017-12-17 08:56:22 +08:00 via Android
这也不大吧
|
20
cxbig 2017-12-17 08:59:46 +08:00
sort -u dict.yml
awk '!a[$0]++' dict.yml |
21
ceclinux 2017-12-17 09:01:01 +08:00 via Android
要是对结果没有顺序要求的,不要想太多,直接 sort 然后 uniq 即可
|
22
fyibmsd 2017-12-17 10:31:45 +08:00
cat old | uniq | tee new
|
23
artandlol 2017-12-17 10:44:36 +08:00 3
一个 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 |
24
ericls 2017-12-17 10:47:05 +08:00 1
from collections import OrderedDict
'\n'.join(OrderedDict.fromkeys(string.splitlines())) |
25
selfAccomplish 2017-12-17 10:51:26 +08:00 via Android
如果楼主的数据是在 window 下面呢,没有 linux 的机子或者数据量大拷不进 linux 的虚拟机。
|
26
cdwyd 2017-12-17 10:53:50 +08:00 via Android
list(set(f.readlines()))
|
27
takeoffyoung 2017-12-17 11:08:28 +08:00
cat xxx.txt | sort | uniq 这样??
|
28
msg7086 2017-12-17 11:23:32 +08:00
@selfAccomplish 那就在 Windows 下用 awk 啊。
|
29
anexplore 2017-12-17 11:41:29 +08:00
1、for i in f.readlines() 改成 for i in f: 是不是更好;
2、查重用 dict 性能好,如果每一行都比较长 建议把 line 换算一下再 put 到 dict 中,要保证顺序就 orderdict |
30
young6 2017-12-17 12:58:22 +08:00 via Android
要是对行顺序没要求,用 cat,sort,uniq 吧,还写啥代码啊。要是行顺序要求不变,python 有有序字典
|
31
leavic 2017-12-17 16:31:34 +08:00
有序字典吧,set 虽然可以去重,但你恢复的时候就无序了。
|
32
wizardoz 2017-12-17 16:35:42 +08:00
dict 可破,用文本当 key,用行号当 value
dict 在判断 in 的时候效率应该吊打 list。 |
33
jyf007 2017-12-17 20:55:58 +08:00
@msg7086
@artandlol @young6 @selfAccomplish @swulling @ioven @rrfeng 别忘了用这个 https://frippery.org/busybox/ ,开一个批处理写成 busybox ash 就有坠吼的环境了,(其实没什么大功能) 我原来写了一个在 windows 处理 netstat 输出的就是这么骚操作. |
34
artandlol 2017-12-17 21:04:36 +08:00 via iPhone
|
35
jyf007 2017-12-17 21:42:58 +08:00
@artandlol 说起来 unix 的好还是只能体现在 busybox 上了,其他不能算是原始的 unix 了
我当时是直接操作 cmd 的窗口就这 vi 写脚本,或者开记事本搞, 完整的 msys2 我装完有 45G 这么大,不够轻盈, 我觉得安利 unix 必须提 busybox 和 dropbear. |
36
warcraft1236 OP |
37
ipwx 2017-12-17 23:18:59 +08:00
24L 是 Python 最优雅的解决方案。
|
38
Lpl 2017-12-17 23:56:50 +08:00
vim 文件
然后 :sort u 会先排序然后取相同行第一行 |
39
lylijincheng 2017-12-18 09:15:55 +08:00
```
Array.from(new Set(longlongtext.split(''))).join('') ``` |
40
wizardoz 2017-12-18 09:45:31 +08:00
@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 排序,保持原来顺序 ... |
41
warcraft1236 OP @wizardoz
多谢,不过再问一个基础的问题,怎么根据 dict 的 values 排序写入文件呢? |
42
araraloren 2017-12-18 11:09:21 +08:00
.say for f.lines.unique(:with(&[eqv])) (in Perl6, f is IO::Handle)
|
43
wizardoz 2017-12-18 13:51:32 +08:00
@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) |
44
shawndev 2017-12-20 21:07:00 +08:00
cat file | uniq
|