[英]compare a wordlist with itself based on first 4 characters
我有一個看起來像這樣的文本文件......
testing
tested
tests
answer
questioned
questions
ask
run
running
我需要找到前 4 個字符相同的單詞,以及這些單詞的數量是否超過 2。預期結果是
testing
tested
tests
如果文件有幾個單詞,則此代碼有效。 較大的輸入文件需要大量時間。
from collections import Counter
mylist=list()
with open('test.txt', 'r') as f:
for i in f.readlines():
mylist.append(i[:4])
myn=Counter(mylist)
import pandas as pd
mys=pd.Series(myn)
myindex=list(mys[mys > 2].index)
newlist=list()
for x in myindex:
with open('test.txt', 'r') as f:
for i in f.readlines():
if x == i[:4]:
newlist.append(i)
有沒有更好的方法來獲得相同的結果?
awk '
{
n = substr($0,1,4);
c[n]++;
w[n] = (length(w[n]) ? w[n]"\n" : "") $0
}
END{ for (n in c) if (c[n] > 2) print w[n] }'
n=substr...
- 提取前 4 個字符 - 這是我們的索引c[n]++
- 保持計數w[n]=...
- 記住單詞,用換行符分隔for(n in c)if(c[n]>2)print w[n]
- 對於每個單詞,如果計數大於 2,則打印該單詞。代碼的主要瓶頸是您正在讀取文件兩次。 在大文件的情況下,最終結果是您將花費至少兩倍的時間。
如果您有能力將文件的全部內容保存在 memory 中,我會按照以下方式做一些事情:(先前的答案已經提出了這一點,但使用了 defaultdict)
Words = dict()
with open('test.txt', 'r') as File:
for line in File:
key = line[:4]
if Words[key]:
Words[key].append(line)
else:
Words[key] = [line,]
Output = []
for key,items in Words.items():
if len(items) > 2:
Output.extend(items)
如果您無法在 memory 中保存您被迫第二次讀取文件的內容,因此一種選擇是將行號存儲在字典中,並在第二次讀取時僅打印存儲的行號:
Words = dict()
with open('test.txt', 'r') as File:
for i,line in enumerate(File):
key = line[:4]
if Words[key]:
Words[key].append(i)
else:
Words[key] = [i,]
LineNumbers = set()
for key,items in Words.items():
if len(items) > 2:
LineNumbers.update(items)
Output = []
with open('test.txt', 'r') as File:
for i,line in enumerate(File):
if i in LineNumbers:
Output.append(line)
注意:如果你調用 File.readlines() 你已經在 memory 在 for 循環的生命周期迭代期間將文件的內容保存在列表中。 如果您使用“for line in File”逐行迭代,我認為迭代是通過按需讀取該行來完成的。
對於 arrays 的 arrays 的 GNU awk 並假設您想要計算唯一字數:
$ cat tst.awk
{
key = substr($0,1,4)
words[key][$0]
}
END {
for ( key in words ) {
if ( length(words[key]) > 2 ) {
for ( word in words[key] ) {
print word
}
}
}
}
$ awk -f tst.awk file
tested
tests
testing
我建議將您的輸入文件的行合並到一個字典中,其中前 4 個字母作為鍵,行列表作為值。 就像是:
from collections import defaultdict
binned_lines = defaultdict{lambda: list()}
with open('test.txt', 'r') as f:
for line in f.readlines():
binned_lines[line[:4]] = binned_lines[line[:4]].append(line)
for key, lines in binned_lines.items():
if len(lines) > 2:
print(lines)
應該為您節省所有索引,並且只需要打開文件一次。
您的代碼可能會使用以下方式test.txt
內容為:
testing
tested
tests
answer
questioned
questions
ask
run
running
和morethan2.py
的內容
from collections import Counter
with open('test.txt', 'r') as f:
lines = f.readlines()
myn=Counter(i[:4] for i in lines)
newlist=[i for i in lines if myn[i[:4]]>2]
print(newlist)
然后python3 morethan2.py
output
['testing\n', 'tested\n', 'tests\n']
說明: f.readlines()
返回行列表,我將其保存為lines
。 然后我使用理解作為Counter
參數( collections.Counter
接受任何可迭代的,不僅是list
)然后我使用帶有條件的list
理解來僅選擇 4 個字母出現超過 2 次的元素。 請注意, collections.Counter
實例的行為類似於dict
,其值為出現次數。 最后我print
換行符,請注意.readlines
默認情況下確實保留尾隨行,因此\n
s。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.