有没有办法根据模式删除字符串中的重复字符串?

时间:2017-02-24 15:06:08

标签: python

我正在使用这种格式的文件:

=Cluster=
SPEC PRD000681;PRIDE_Exp_Complete_Ac_22491.xml;spectrum=1074 true
SPEC PRD000681;PRIDE_Exp_Complete_Ac_22498.xml;spectrum=2950 true


=Cluster=
SPEC PRD000681;PRIDE_Exp_Complete_Ac_22498.xml;spectrum=1876 true
SPEC PRD000681;PRIDE_Exp_Complete_Ac_22498.xml;spectrum=3479 true
SPEC PRD000681;PRIDE_Exp_Complete_Ac_22498.xml;spectrum=3785 true
SPEC PRD000681;PRIDE_Exp_Complete_Ac_22498.xml;spectrum=3785 true

=Cluster=
SPEC PRD000681;PRIDE_Exp_Complete_Ac_22493.xml;spectrum=473 true
SPEC PRD000681;PRIDE_Exp_Complete_Ac_22493.xml;spectrum=473 true

正如您所看到的,每条SPEC线都不同,除了两条重复字符串频谱的数量。我想做的是在模式=Cluster=之间获取每一块信息,并检查是否有重复频谱值的行。如果有多行重复,除了一行之外全部删除。

输出文件应如下所示:

=Cluster=
SPEC PRD000681;PRIDE_Exp_Complete_Ac_22491.xml;spectrum=1074 true
SPEC PRD000681;PRIDE_Exp_Complete_Ac_22498.xml;spectrum=2950 true


=Cluster=
SPEC PRD000681;PRIDE_Exp_Complete_Ac_22498.xml;spectrum=1876 true
SPEC PRD000681;PRIDE_Exp_Complete_Ac_22498.xml;spectrum=3479 true
SPEC PRD000681;PRIDE_Exp_Complete_Ac_22498.xml;spectrum=3785 true

=Cluster=
SPEC PRD000681;PRIDE_Exp_Complete_Ac_22493.xml;spectrum=473 true

我在itertools模块中使用groupby。我假设我的输入文件名为f_input.txt,输出文件名为new_file.txt,但此脚本也删除了SPEC字样......而且我不知道为了不这样做我可以改变什么。

from itertools import groupby

data = (k.rstrip().split("=Cluster=") for k in open("f_input.txt", 'r'))
final = list(k for k,_ in groupby(list(data)))

with open("new_file.txt", 'a') as f:
    for k in final:
        if k == ['','']:
            f.write("=Cluster=\n")
        elif k == ['']:
            f.write("\n\n")
        else:
            f.write("{}\n".join(k))

编辑: 新条件。有时行号的一部分可能会改变,例如:

=Cluster=
SPEC PRD000681;PRIDE_Exp_Complete_Ac_22498.xml;spectrum=1876 true
SPEC PRD000681;PRIDE_Exp_Complete_Ac_22498.xml;spectrum=3479 true
SPEC PRD000681;PRIDE_Exp_Complete_Ac_22498.xml;spectrum=3785 true
SPEC PRD000682;PRIDE_Exp_Complete_Ac_22498.xml;spectrum=3785 true

如您所见,最后一行更改了部件PRDnumber。一种解决方案是检查光谱数,并基于重复光谱去除线。

这将是一个解决方案:

=Cluster=
SPEC PRD000681;PRIDE_Exp_Complete_Ac_22498.xml;spectrum=1876 true
SPEC PRD000681;PRIDE_Exp_Complete_Ac_22498.xml;spectrum=3479 true
SPEC PRD000681;PRIDE_Exp_Complete_Ac_22498.xml;spectrum=3785 true

4 个答案:

答案 0 :(得分:3)

我就是这样做的。

file_in = r'someFile.txt'   
file_out = r'someOtherFile.txt'
with open(file_in, 'r') as f_in, open(file_out, 'w') as f_out:
    seen_spectra = set()
    for line in f_in:
        if '=Cluster=' in line or line.strip() == '':
            seen_spectra = set()
            f_out.write(line)
        else:
            new_spectrum = line.rstrip().split('=')[-1].split()[0]
            if new_spectrum in seen_spectra:
                continue
            else:
                f_out.write(line)
                seen_spectra.add(new_spectrum)      

这不是groupby解决方案,而是您可以轻松遵循和调试的解决方案。正如你在评论中提到的,你的这个文件是16GB大,加载到内存可能不是最好的想法..

  

编辑:“每个群集都有一个特定的频谱。一个群集中不可能有一个规范而另一个群集中的规范相同”

file_in = r'someFile.txt'   
file_out = r'someOtherFile.txt'
with open(file_in, 'r') as f_in, open(file_out, 'w') as f_out:
    seen_spectra = set()
    for line in f_in:
        if line.startswith('SPEC'):
            new_spectrum = line.rstrip().split('=')[-1].split()[0]
            if spectrum in seen_spectra:
                continue
            else:
                seen_spectra.add(new_spectrum)      
                f_out.write(line)          
        else:
            f_out.write(line)

答案 1 :(得分:2)

这将打开包含原始代码的文件以及将为每个组输出唯一行的新文件。

seen是一个set,非常适合查看其中是否存在某些内容。

datalist,会跟踪"=Cluster="群体的迭代次数。

然后,您只需查看每个组的每一行(在i中指定为data)。

如果seen中的行不存在则会添加。

with open ("input file", 'r') as in_file, open("output file", 'w') as out_file:
    data = [k.rstrip().split("=Cluster=") for k in in_file]
    for i in data:
        seen = set()
        for line in i:
            if line in seen:
                continue
            seen.add(line)
            out_file.write(line)

修改:将seen=set()移至for i in data以重置该设置,否则"=Cluster="始终存在,并且不会为data内的每个组打印{1}}。

答案 2 :(得分:1)

Python中最短的解决方案:p

For Row = 3 To y - 1

Col = 0
OutputCol = OutputCol + 1

    For Col = 3 To x - 2

    Cells(Col + 3, OutputCol).Value = "L" + Cells(5, Col + 1).Value + "C" + Cells(6, Row).Value + "  " + "EXEC TRANEXEC, " + Line + Cells(5, Col + 1).Value + "," + Company + Cells(6, Row).Value

    Next Col

Next Row

输出:

import os
os.system("""awk 'line != $0; { line = $0 }' originalfile.txt > dedup.txt""")

(如果您使用的是Windows,则可以使用Gow轻松安装awk。)

答案 3 :(得分:0)

使用re.search()函数和自定义spectrums设置对象的解决方案仅保留唯一spectrum个数字:

with open('f_input.txt') as oldfile, open('new_file.txt', 'w') as newfile:
    spectrums = set()
    for line in oldfile:
        if '=Cluster=' in line or not line.strip():
            newfile.write(line)
        else:
            m = re.search(r'spectrum=(\d+)', line)
            spectrum = m.group(1)
            if spectrum not in spectrums:
                spectrums.add(spectrum)
                newfile.write(line)