#python #python-3.x #split
Вопрос:
Можно ли разделить строку на фразу (потенциально более одного слова) в Python 3 справа налево (только первое вхождение)?
В настоящее время я могу разделить строку на основе списка фраз, но у меня есть крайний случай, когда, если в строке встречается более одной из указанных фраз, она разделяется на обе.
Проблема
Приведен пример CSV-файла, содержащего следующее:
предложения | |
---|---|
ЭТО ТРЕТЬЕ ПРЕДЛОЖЕНИЕ | 1 |
ЭТО ВТОРОЕ ПРЕДЛОЖЕНИЕ | 2 |
Я СОДЕРЖУ ОДИН, НО ТАКЖЕ И ДВА | 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 дважды из-за того, что оно содержит две фразы из списка фраз.
Желаемый результат
Я знаю, что из перечисленных фраз, которые нужно разделить, она всегда будет последней справа. Поэтому я хотел бы захватить только первое появление справа налево.
ПРИМЕЧАНИЕ: «Фраза» может содержать одно или несколько слов.
Возможно ли это? И если да, то как я могу этого достичь?
Комментарии:
1. Основываясь на вашем обновлении
words => phrases
, я отредактировал свой ответ.2. Мне неясно, но для последнего примера предложения вы хотите разделить оба (ОДИН и ДВА) или просто разделить на ДВА, так как это самое правое?
3. @JustinEzequiel Просто делится на ДВОИХ, потому что это самое правое.
4. Тогда любой из приведенных ниже ответов должен подействовать на вас.
Ответ №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')
Комментарии:
1. Ах, я и не знал об
string.rfind()
этом . Пытаясь понять это, можете ли вы объяснить, чтоstring[:i]
такое иstring[i::]
что такое? Я просто раньше не видел такого синтаксиса.2. Теперь он у меня есть.
[Start : Stop : Steps]
. Такstring[i::]
же как и нарезка строки, начинающейся с индекса, которыйrfind()
возвращается без остановки или шагов.3. Извините, что так долго не отвечаю, но да, это правильно. Если на ваш вопрос получен ответ, пожалуйста, обязательно отметьте решение.
4. Спасибо @LaytonGB. Я отметил это как правильный ответ. Один дополнительный вопрос, однако , вместо того, чтобы задавать фразу как
string[i::]
, как я могу установить остановку среза на длину слова, на случай, если после него будет что-то еще?5. Превосходно! Ты знаешь своего Питона! 🙂 Это добавляет дополнительную страховочную сетку. Еще раз спасибо.
Ответ №2:
Я верю, что это сработает, если вы используете «rsplit()» вместо «split ()».
Комментарии:
1. ОП использует
re.split
.re.rsplit
не существует.2. ОП тянется не к тому инструменту, на который это похоже в первую очередь. Предполагая, что мы понимаем их проблему, нет причин использовать
re.split
.3. Глядя на
rsplit()
него, не похоже, что он принимает регулярное выражение? Мне нужно передать регулярное выражение, чтобы определить слово, которое нужно разделить.4. Неважно, я думаю, что сначала мне было непонятно, что они хотят разделиться только на определенные слова.
5. Я открыт для других способов достижения желаемого результата. Я только начал использовать
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', '')
Комментарии:
1. Интересный подход. Что, если «слово» для поиска состояло из двух слов? Я использовал термин «слово» для приведенного здесь примера, но, оглядываясь назад, это могло ввести в заблуждение. Потенциально это тоже фраза. Больше похоже на заданную строку.
2. @Ян, Это очень вводит в заблуждение, да.
3. Я обновлю пример, чтобы использовать «фразу» вместо «слова». Однако они все еще являются элементами списка.