Более быстрый и удобный способ перевернуть предложения в строке?

Хорошо, я ищу способ перевернуть предложения в строке быстро и лаконично.

Например, если бы я хотел преобразовать «Раз два три. Четыре пять шесть». на "Три два один. Шесть пять четыре".

Вот мой наивный подход:

def reverse_sentences(str):
 newlist=str.split(".")   
 newstr=''
 for s in newlist[0:-1]:
   words=s.split()
   words=words[::-1]
   words[0]=words[0][0].upper()+words[0][1:]
   words[-1]=words[-1][0].lower()+words[-1][1:]
   for e in range(len(words)):
      words[e].strip()
      if words[e] != words[-1]:
           newstr+=words[e]+" "
      else:
           newstr+=words[e]
   newstr+=". "
 return newstr

Любой более быстрый и более Pythonic способ сделать это, например. понимание списка и прочее.


person garlfd    schedule 01.03.2014    source источник
comment
что, если вход One, two three.? Как вы относитесь к ,?   -  person zhangxaochen    schedule 01.03.2014
comment
Не уверен, предположим, что существуют только точки, а не запятые. Это было бы интересное решение, если бы можно было точно это понять.   -  person garlfd    schedule 01.03.2014


Ответы (2)


Я бы, вероятно, написал что-то подобное, используя выражения генератора (для ленивая оценка):

def reverse_sentences(text):
    sentences = text.split('.')
    reversed_words = (reversed(words.split()) for words in sentences)
    rejoined_words = (' '.join(words) for words in reversed_words)
    capitalized_sentences = (sentence.capitalize() for sentence in rejoined_words)
    return '. '.join(capitalized_sentences)

reverse_sentences("One two three. Four five six.")

Я предпочитаю эту функцию «однострочной», поскольку ее легче поддерживать (например, если вы хотите добавить обработку пунктуации или strip-ping пробел).

Разбивая это на составные части (используя списковые включения для иллюстрация):

In [1]: text = "One two three. Four five six."

In [2]: text
Out[2]: 'One two three. Four five six.'

In [3]: sentences = text.split('.')

In [4]: sentences
Out[4]: ['One two three', ' Four five six', '']

In [5]: reversed_words = [words.split()[::-1] for words in sentences]

In [6]: reversed_words
Out[6]: [['three', 'two', 'One'], ['six', 'five', 'Four'], []]

In [7]: rejoined_words= [' '.join(words) for words in reversed_words]

In [8]: rejoined_words
Out[8]: ['three two One', 'six five Four', '']

In [9]: capitalized_sentences = [sentence.capitalize() for sentence in rejoined_words]

In [10]: capitalized_sentences
Out[10]: ['Three two one', 'Six five four', '']

In [11]: '. '.join(capitalized_sentences)
Out[11]: 'Three two one. Six five four. '

Примечание:

Скорость

Вы, наверное, хотите знать, насколько быстро это работает...

Здесь пригодится timeit.

Ваш пример

> python -m timeit <<EOF
def reverse_sentences(str):
 newlist=str.split(".")
 newstr=''
 for s in newlist[0:-1]:
   words=s.split()
   words=words[::-1]
   words[0]=words[0][0].upper()+words[0][1:]
   words[-1]=words[-1][0].lower()+words[-1][1:]
   for e in range(len(words)):
      words[e].strip()
      if words[e] != words[-1]:
           newstr+=words[e]+" "
      else:
           newstr+=words[e]
   newstr+=". "
 return newstr

reverse_sentences("One two three. Four five six.")
EOF
100000000 loops, best of 3: 0.012 usec per loop

Мой пример

> python -m timeit <<EOF
def reverse_sentences(text):     
    sentences = text.split('.')                                                                      
    reversed_words = (reversed(words.split()) for words in sentences)
    rejoined_words = (' '.join(words) for words in reversed_words)
    capitalized_sentences = (sentence.capitalize() for sentence in rejoined_words)
    return '. '.join(capitalized_sentences)

reverse_sentences("One two three. Four five six.")
EOF
100000000 loops, best of 3: 0.012 usec per loop

пример zhangxaochen

> python -m timeit <<EOF
t="One two three. Four five six."
' '.join(' '.join(sentence.lower().split()[::-1]).capitalize()+'.' for sentence in t.split('.')[:-1])
EOF                                                                  
100000000 loops, best of 3: 0.012 usec per loop

Вывод

Оптимизируйте для удобства чтения и сопровождения, придерживаясь Дзен Python и своего кода. будет "более питоническим".

person Johnsyweb    schedule 01.03.2014
comment
В Python есть функция капитализации?! Вау спасибо за это! - person garlfd; 01.03.2014
comment
@garlfd: ​​str.capitalize(), да! - person Johnsyweb; 01.03.2014
comment
и, может быть, применить strip() к конечному результату, чтобы избавиться от лишнего пробела в конце? - person lessthanl0l; 01.03.2014
comment
@lessthanl0l: Ага. Много настроек, которые можно сделать. Мой ответ касается подхода. - person Johnsyweb; 01.03.2014

Вот длинный однострочник с использованием понимания списка и нарезки и str.join:

In [79]: t="One two three. Four five six."

In [80]: ' '.join(' '.join(sentence.lower().split()[::-1]).capitalize()+'.'
    ...:                              for sentence in t.split('.')[:-1])
Out[80]: 'Three two one. Six five four.'
person zhangxaochen    schedule 01.03.2014
comment
???? Это конечно лаконичнее, что и просили. Это не кажется более быстрым (см. мой ответ) или более Pythonic (см. PEP 20), но мне нравится ваш функциональный подход. - person Johnsyweb; 01.03.2014
comment
@Johnsyweb да, это не быстрее, просто для удовольствия;) - person zhangxaochen; 01.03.2014