【问题标题】:Python: How to split a string by phrase from right to left (first occurrence only)Python:如何按短语从右到左拆分字符串(仅限第一次出现)
【发布时间】:2021-07-19 17:17:01
【问题描述】:

是否可以在 Python 3 中从右到左(仅第一次出现)拆分短语(可能超过一个单词)上的字符串?

目前我可以根据短语列表拆分字符串,但我有一个极端情况,如果字符串中出现多个指定短语,那么它会同时拆分。

问题

给定一个包含以下内容的示例 CSV:

SENTENCES
THIS IS SENTENCE THREE 1
THIS IS SENTENCE TWO 2
I CONTAIN ONE BUT ALSO TWO 3

我的代码打开一个 CSV,循环遍历每一行,然后拆分指定的短语:

import re
import csv

def split_phrase(string):
    phrases = ['ONE', 'TWO', 'THREE']
    print(f'Raw: {string}')
    split_phrase = '' # Only needed for testing purposes to prevent error on output
    for phrase in phrases:
        if phrase in string:
            list = re.split(f'\\b({phrase})\\b', string)
            print(f'Split: {list}')
            sentence = list[0]
            split_phrase = list[1]
            print(f'Phrase: {split_phrase}')

    return sentence, split_phrase

input_dir = 'input1/'
output_dir = 'output1/'
filename = 'demo.csv'

with open(input_dir + filename, 'r') as input_csv:
    csv_reader = csv.reader(input_csv)
    data = list(csv_reader)
    input_csv.close()

    for row in data[1:]: # Ignore the header row
        sentence = row[0] # First column
        sentence = split_phrase(sentence) # Split out specified phrase

我得到以下输出:

$ python3 demo.py
Raw: THIS IS SENTENCE THREE
Split: ['THIS IS SENTENCE ', 'THREE', '']
Phrase: THREE
Raw: THIS IS SENTENCE TWO
Split: ['THIS IS SENTENCE ', 'TWO', '']
Phrase: TWO
Raw: I CONTAIN ONE BUT ALSO TWO
Split: ['I CONTAIN ', 'ONE', ' BUT ALSO TWO']
Phrase: ONE
Split: ['I CONTAIN ONE BUT ALSO ', 'TWO', '']
Phrase: TWO

注意:最后一个句子由 for 循环处理两次,因为它包含短语列表中的两个短语。

期望的结果

我知道在列出的要拆分的短语中,它始终是右侧的最后一个。所以我想只从右到左抓取第一个匹配项

注意:“短语”可以包含一个或多个单词。

这可能吗?如果是这样,我该如何实现?

【问题讨论】:

  • 根据您的更新words => phrases 我已经编辑了我的答案。
  • 我不清楚,但对于最后一个例句,你想要 both 拆分(ONE 和 TWO)还是只拆分 TWO,因为那是最右边的?
  • @JustinEzequiel 只是拆分两个,因为它是最右边的。
  • 那么下面的任何答案都应该适合你。

标签: python python-3.x split


【解决方案1】:

我已通过使用string.rfind() 从字符串末尾搜索并遍历可能的短语列表来回答这个问题。可能有更好的不重复的方法,但这是我发现的最好的。

one = "THIS IS SENTENCE THREE"
two = "THIS IS SENTENCE TWO"
three = "I CONTAIN ONE BUT ALSO TWO"
four = "I CONTAIN ONE BUT ALSO TWO AND SOME MORE TEXT"
phrases = ['ONE', 'TWO', 'THREE']

def find_words(phrases, string):
    i = -1
    p = ""
    for phrase in phrases:
        newI = string.rfind(phrase)
        if newI > i:
            i = newI
            p = phrase
    return (string[:i], string[i:i+len(p)], string[i+len(p)::])

print(find_words(phrases, one))
print(find_words(phrases, two))
print(find_words(phrases, three))
print(find_words(phrases, four))

输出:

('THIS IS SENTENCE ', 'THREE', '')
('THIS IS SENTENCE ', 'TWO', '')
('I CONTAIN ONE BUT ALSO ', 'TWO', '')
('I CONTAIN ONE BUT ALSO ', 'TWO', ' AND SOME MORE TEXT')

【讨论】:

  • 啊,我不知道string.rfind()。在试图理解它时,你能解释一下string[:i]string[i::] 是什么吗?我以前没见过这种语法。
  • 我现在知道了。 [Start : Stop : Steps]。所以string[i::] 正在从rfind() 返回的索引开始分割字符串,没有停止或步骤。
  • 很抱歉花了这么长时间才回复,但是是的,这是正确的。如果您的问题得到解答,请务必标记解决方案。
  • 感谢@LaytonGB。我已将此标记为正确答案。还有一个额外的问题,而不是将短语设置为string[i::],如何将切片停止设置为单词的长度,以防万一后面还有其他内容?
  • 太棒了!你知道你的 Python! :) 这增加了额外的安全网。再次感谢。
【解决方案2】:

我相信如果你使用“rsplit()”而不是“split()”,它会起作用

【讨论】:

  • OP 正在使用re.splitre.rsplit 不存在。
  • OP 一开始就在寻找错误的工具。假设我们了解他们的问题,没有理由使用re.split
  • 看看rsplit() 好像它不接受正则表达式?我需要传入一个正则表达式来识别要拆分的单词。
  • 没关系,我认为起初我并不清楚他们想要拆分特定的单词。
  • 我愿意接受其他方式来达到预期的结果。我刚开始使用re.split() 作为正则表达式,但我的单词列表是已知的。它们比此处列出的演示要大,但仍然已知。我只需要确保它是一个单独的词,而不是另一个词的一部分。即ONE 应该匹配但不是SOMEONE。这就是我使用正则表达式的原因。
【解决方案3】:

我认为关键是拆分成单词,然后反转该列表,然后搜索所有命中并选择最小的数字:

def split_word(string):
    words = ['ONE', 'TWO', 'THREE']
    search = string.split()
    rsearch = list(reversed(search))
    locs = [rsearch.index(w) for w in words if w in rsearch]
    if not locs:
        return None
    target = len(search) - min(locs) - 1
    return ' '.join(search[0:target]), search[target], ' '.join(search[target+1:])

print(split_word("THIS IS SENTENCE THREE"))
print(split_word("THIS IS SENTENCE TWO"))
print(split_word("I CONTAIN ONE BUT ALSO TWO"))

输出:

('THIS IS SENTENCE', 'THREE', '')
('THIS IS SENTENCE', 'TWO', '')
('I CONTAIN ONE BUT ALSO', 'TWO', '')

【讨论】:

  • 有趣的方法。如果要搜索的“单词”由两个单词组成怎么办?我在此处的示例中使用了“单词”一词,但事后看来,这可能具有误导性。可能它也是一个短语。更多的设置字符串。
  • @Ian 这是非常具有误导性的。
  • 我将更新示例以使用“短语”而不是“单词”。然而,它们仍然是列表中的项目
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-12-15
  • 1970-01-01
  • 2014-03-22
  • 1970-01-01
  • 2016-06-07
  • 2021-12-08
  • 2017-04-09
相关资源
最近更新 更多