簡體   English   中英

根據前 4 個字符將單詞表與其自身進行比較

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM