Самый питонский способ объединения строк - PullRequest
38 голосов
/ 25 января 2010

Учитывая этот безобидный маленький список:

>>> lst = ['o','s','s','a','m','a']

Моя цель состоит в том, чтобы объединить маленьких дьяволов с помощью одного из следующих способов:

A.простая старая функция для выполнения работы, короткая, без импорта

>>> ''.join(lst)
'ossama'

B.лямбда, лямбда, лямбда

>>> reduce(lambda x, y: x + y, lst)
'ossama'

C.глобализация (ничего не делать, импортировать все)

>>> import functools, operator
>>> functools.reduce(operator.add, lst)
'ossama'

Пожалуйста, предложите другие питонские способы решения этой великодушной задачи.

Пожалуйста, оцените (уровень Питона) и оцените решения, дающие краткие объяснения.

В этом случае самое питонское решение - лучшее решение для кодирования?

Ответы [ 6 ]

59 голосов
/ 25 января 2010
''.join(lst)

единственный питонический путь:

  • ясно (то, что делают все большие мальчики и что они ожидают увидеть),
  • простой (дополнительный импорт не требуется, стабильный для всех версий),
  • быстро (написано на С) и
  • лаконично (к пустой строке присоединяются элементы итерируемого!).
33 голосов
/ 25 января 2010

Взгляните на эссе Гвидо , посвященное оптимизации Python, оно охватывает преобразование списков чисел в строки. Если у вас нет веской причины поступить иначе, используйте пример join.

18 голосов
/ 25 января 2010

Конечно, это join. Откуда мне знать? Давайте сделаем это очень глупо:
Если бы проблема заключалась только в добавлении 2 строк, вы, скорее всего, использовали бы str1 + str2. Что нужно, чтобы получить это на следующий уровень? Инстинктивно, для большинства (я думаю), будет использовать sum. Давайте посмотрим, как это происходит:

In [1]: example = ['a', 'b', 'c']
In [2]: sum(example, '')
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython console> in <module>()
TypeError: sum() can't sum strings [use ''.join(seq) instead]

Вау! Python просто сказал мне, что использовать! :)

7 голосов
/ 25 января 2010

Вот наименее Pythonic способ:

out = ""
for x in range(len(lst)):
  for y in range(len(lst)):
    if x + y == len(lst)-1:
        out = lst[y] + out
6 голосов
/ 25 января 2010

Я сам использую способ соединения, но в Python 2.6 есть базовый тип, который используется мало: bytearray .

Байт-массивы могут быть невероятно полезными - для строк, содержащих тексты, так как лучше всего использовать в юникоде способ «соединения», но если вы имеете дело с двоичными данными, байт-массивы могут быть более питонным и более эффективным:

>>> lst = ['o','s','s','a','m','a']
>>> a = bytearray(lst)
>>> a
bytearray(b'ossama')
>>> print a
ossama

это встроенный тип данных: нет необходимости в импорте - просто используйте затем - и вы можете использовать байтовый массив вместо списка для начала - так что они должны быть более эффективными, чем «объединение», поскольку нет копирование данных для получения строкового представления для байтового массива.

4 голосов
/ 25 января 2010

Отличный ответ от SilenGhost, НО, всего несколько слов о представленной reduce "альтернативе"

Если у вас нет очень-очень ОЧЕНЬ веских причин для объединения строк с использованием + или operator.add (наиболее частая, когда у вас мало фиксированного числа строк), Вы должны использовать всегда join.

Просто потому, что каждый + генерирует новую строку, которая является объединением двух строк, если соединение, которое генерирует только одну финальную строку. Итак, представьте, что у вас есть 3 строки:

A + B + C
-->
D = A + B
final = D + C

Хорошо, кажется, не так много, но вы должны зарезервировать память для D. Кроме того, из-за использования строк на python, генерирующих новую промежуточную строку, это как-то дорого ...

Теперь с 5 строками

A + B + C + D + E
-->
F = A + B
G = F + C
H = G + D
final = H + E

Предполагая лучший сценарий (если мы выполним (A + B) + (C + D) + E, у нас закончится три промежуточных строки в памяти одновременно), это создаст 3 промежуточные строки ... Вы нам нужно сгенерировать новый объект python, зарезервировать пространство памяти, освободить память несколько раз ... Также накладные расходы при вызове функции Python (что не мало)

Теперь подумайте об этом с 200 строками. В итоге мы получим смехотворно большое количество промежуточных строк, каждая из которых потребляет достаточно много времени для объединения в полный список над Python и вызова большого количества operator.add функций, каждая из которых имеет свои издержки ... Даже если Вы используете reduce функции, это не поможет. Эта проблема должна решаться с помощью другого подхода: join, который генерирует только ONE завершенную строку Python, последнюю и вызывает ОДНУ функцию Python.

(конечно, join или другая аналогичная специализированная функция для массивов)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...