在特定短语后切割字符串?

11 投票
6 回答
30367 浏览
提问于 2025-04-15 15:26

我有一堆字符串需要处理。这些字符串基本上是一个描述符后面跟着一些代码。我只想保留描述符。

'a descriptor dps 23 fd'
'another 23 fd'
'and another fd'
'and one without a code'

上面的代码是 dps23fd。它们的顺序可以随意,彼此之间没有关系,并且可能根本不存在(就像最后一个例子那样)。

这些代码的列表是固定的(或者至少可以预测),所以假设代码不会出现在合法的描述符中,我该如何去掉第一个代码之后的所有内容呢?

我在使用Python。

6 个回答

1

在编程中,有时候我们会遇到一些问题,特别是在使用某些工具或库的时候。这些问题可能会让我们感到困惑,尤其是当我们刚开始学习编程的时候。

比如,有人可能在使用某个特定的功能时,发现它没有按照预期工作。这时候,他们可能会去网上查找解决办法,比如在StackOverflow这样的论坛上提问。

在提问时,清楚地描述问题是非常重要的。这样其他人才能理解你的困扰,并给出有效的建议。通常,提问者会提供一些代码示例,说明他们的代码是如何运行的,以及遇到的问题是什么。

总之,编程中遇到问题是很正常的,关键是要学会如何有效地寻求帮助,并清晰地表达自己的问题。

codes = ('12', 'dps', '23')

def get_descriptor(text):
    words = text.split()
    for c in codes:
        if c in words:
            i = words.index(c)
            return " ".join(words[:i])
    raise ValueError("No code found in `%s'" % (text))
2

你似乎在描述的内容像这样:

def get_descriptor(text):
    codes = ('12', 'dps', '23')
    for c in codes:
        try:
            return text[:text.index(c)].rstrip()
        except ValueError:
            continue

    raise ValueError("No descriptor found in `%s'" % (text))

比如说,

>>> get_descriptor('a descriptor dps 23 fd')
'a descriptor'
28

简单来说,正如@THC4K在评论中提到的:

string.split(pattern, 1)[0]

这里的string是你最开始的字符串,pattern是你想要“分割”的模式,1表示最多只分割一次,而[0]则表示取分割后返回的第一个元素。

实际操作:

>>> s = "a descriptor 23 fd"
>>> s.split("23", 1)[0]
'a descriptor '
>>> s.split("fdasfdsafdsa", 1)[0]
'a descriptor 23 fd'

这是一种更简洁的写法,虽然我之前写的内容也会保留在这里。

如果你需要去掉多个模式,这里可以使用reduce这个内置函数:

>>> string = "a descriptor dps foo 23 bar fd quux"
>>> patterns = ["dps", "23", "fd"]
>>> reduce(lambda s, pat: s.split(pat, 1)[0], patterns, string)
'a descriptor '
>>> reduce(lambda s, pat: s.split(pat, 1)[0], patterns, "uiopuiopuiopuipouiop")
'uiopuiopuiopuipouiop'

这基本上是说:对于每一个patpatterns中:拿string来反复应用string.split(pat, 1)[0](就像上面解释的那样),每次都在上一次返回的结果上操作。你可以看到,如果字符串中没有任何模式,原始字符串还是会被返回。


最简单的答案是结合使用列表/字符串切片和string.find

>>> s = "a descriptor 23 fd"
>>> s[:s.find("fd")]
'a descriptor 23 '
>>> s[:s.find("23")]  
'a descriptor '
>>> s[:s.find("gggfdf")] # <-- look out! last character got cut off
'a descriptor 23 f'

一个更好的方法(为了避免在模式缺失时切掉最后一个字符,当s.find返回-1时)可能是把它放在一个简单的函数里:

>>> def cutoff(string, pattern):
...     idx = string.find(pattern)
...     return string[:idx if idx != -1 else len(string)]
... 
>>> cutoff(s, "23")
'a descriptor '
>>> cutoff(s, "asdfdsafdsa")
'a descriptor 23 fd'

这里的[:s.find(x)]语法意味着从字符串的第0个索引开始,取到冒号右边的部分;在这个例子中,右边的部分是s.find的结果,它返回你传入字符串的索引。

撰写回答