【问题标题】:remove string characters after first instance in python在python中的第一个实例后删除字符串字符
【发布时间】:2018-09-23 23:36:36
【问题描述】:

我认为这应该很简单,但现在是星期五下午,我的大脑不太清楚。

我正在编写一个小文件解析,下面的代码将一组字符串转换为一个数据框,将字符串拆分。

以下是一些示例字符串:

1. NC_002523_1  Serratia entomophila plasmid pADAP, complete sequence.

2. NZ_CM003366_0    Pantoea ananatis strain CFH 7-1 plasmid CFH1-7plasmid2, whole genome shotgun sequence.

3. NZ_CP014491_0    Escherichia coli strain G749 plasmid pG749_3, complete sequence.

4. NC_015062_0  Rahnella sp. Y9602 plasmid pRAHAQ01, complete sequence.

我没想到在第 4 个条目中 sp 之后会出现 .,正如您在下面的代码中看到的那样,我拆分 . 以获得排名的第一个整数。因此,我得到一个 ValueError,表明列数比预期的多。

# Define the column headers for the section since the file's are too verbose and ambiguous
SigHit.Columns = ["Rank", "ID", "Description"]

# Store the table of loci and associated data (tab separated, removing last blank column.

# Use StringIO object to imitate a file, which means that we can use read_table and have the dtypes
# assigned automatically (necessary for functions like min() to work correctly on integers)

SigHit.Table = pd.read_table(
               io.StringIO(u'\n'.join([row.rstrip('.') for row in sighits_section])),
               sep='\.|\t',
               engine='python',
               names=SigHit.Columns)

我能想到的最简单的解决方案(直到其他一些边缘情况破坏它)是替换每个.,除了第一次出现。如何做到这一点?

我看到 maxreplace argument 到 .replace 有一个,但这与我想要的相反,只会替换第一个实例。

有什么建议吗? (更强大的解析方法也是一个有效的选择,但我必须更改的代码越少越好)。

【问题讨论】:

  • 您的1. 等后面是制表符还是空格?
  • 您可以在前 2 个空格处 split 您的数据。 row.split(None,2) 而不是 row.rstrip。这会将空格和制表符分隔成长度为 3 的列表
  • 1. 后跟一个空格,字母数字 ID 后跟一个制表符,然后是描述(我没有编写输出文件的软件:P)

标签: python string replace


【解决方案1】:

使用积极的后视来确保点前面有一个数字 - sep='(?<=\d)\.|\t'

例如:

import pandas as pd
import io

columns = ["Rank", "ID", "Description"]

sighits_section = '''1. NC_002523_1\tSerratia entomophila plasmid pADAP, complete sequence.
2. NZ_CM003366_0\tPantoea ananatis strain CFH 7-1 plasmid CFH1-7plasmid2, whole genome shotgun sequence.
3. NZ_CP014491_0\tEscherichia coli strain G749 plasmid pG749_3, complete sequence.
4. NC_015062_0\tRahnella sp. Y9602 plasmid pRAHAQ01, complete sequence.'''.splitlines()

tab = pd.read_table(io.StringIO(u'\n'.join([row.rstrip('.') for row in sighits_section])),
                    sep='(?<=\d)\.|\t',
                    engine='python',
                    names=columns)

print(tab)

打印

   Rank              ID                                        Description
0     1     NC_002523_1  Serratia entomophila plasmid pADAP, complete s...
1     2   NZ_CM003366_0  Pantoea ananatis strain CFH 7-1 plasmid CFH1-7...
2     3   NZ_CP014491_0  Escherichia coli strain G749 plasmid pG749_3, ...
3     4     NC_015062_0  Rahnella sp. Y9602 plasmid pRAHAQ01, complete ...

为了额外的安全,您可能希望在点旁边添加空格作为分隔符 - sep='(?&lt;=\d)\.\s|\t' - 以防万一,例如10.1 在您的描述中某处。这无论如何都不是防弹的。

更安全 - 当您一次处理一行数据时,您可以使用sep='(?&lt;=^\d)\.\s|\t' 添加一个断言,即该数字也是字符串中的第一个字符。但是,这将在高于 10 的数字上崩溃。

【讨论】:

  • 这看起来是迄今为止最强大的。十进制数应该没有理由潜入(无论如何都是非格式错误的文件)。不需要对代码进行太多更改的奖励积分哈哈
  • @JoeHealey 谢谢 - 我已经添加了另一个修改以确保数字位于字符串的开头 - 可能是最安全的,但这取决于你得到多少结果
  • 解决最后的小更新,是的,数字可以大于 10。理论上,任何整数都是有效的,实际上它不太可能大于 200-300。
【解决方案2】:

天真的方法

替换除第一次出现的.

line = "4. NC_015062_0  Rahnella sp. Y9602 plasmid pRAHAQ01, complete sequence."
count = line.count(".")
line = line[::-1].replace(".", "", count-1)[::-1]

这里是一个班轮

row[::-1].replace(".","",row.count(".")-1)[::-1]

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-06-24
    • 2016-10-16
    • 1970-01-01
    • 2011-04-11
    • 1970-01-01
    • 2011-06-01
    相关资源
    最近更新 更多