Подтвердить что ты не робот

Какой лучший способ конкатенировать строку в python?

Понять "лучше" как более быструю, элегантную и удобочитаемую.

У меня есть две строки (a и b), которые могут быть нулевыми или нет. И я хочу объединить их, разделенные дефисом, только если оба значения не равны нулю:

a - b

a (если b равно null)

b (где a равно null)

4b9b3361

Ответ 1

# Concatenates a and b with ' - ' or Coalesces them if one is None
'-'.join([x for x in (a,b) if x])

Edit
Вот результаты этого алгоритма (обратите внимание, что None будет работать так же, как ''):

>>> '-'.join([x for x in ('foo','bar') if x])
'foo-bar'
>>> '-'.join([x for x in ('foo','') if x])
'foo'
>>> '-'.join([x for x in ('','bar') if x])
'bar'
>>> '-'.join([x for x in ('','') if x])
''

* Также обратите внимание на то, что оценка Рафаэля в его сообщении ниже показала разницу в 0,0002 секунды над 1000 итерациями метода фильтра, можно предположить, что такая небольшая разница может быть связана с несогласованностью в доступных системных ресурсах во время запуска script. Я выполнил его timeit-реализацию на нескольких итерациях и обнаружил, что любой алгоритм будет быстрее примерно в 50% случаев, ни с большим отрывом. Таким образом, они в основном эквивалентны.

Ответ 2

Как насчет чего-то простого:

# if I always need a string even when `a` and `b` are both null,
# I would set `output` to a default beforehand.
# Or actually, as Supr points out, simply do `a or b or 'default'`
if a and b:
    output = '%s - %s' % (a, b)
else:
    output = a or b

Изменить: много интересных решений в этой теме. Я выбрал это решение, потому что я подчеркивал удобочитаемость и быстроту, по крайней мере, с точки зрения реализации. Это не самое масштабируемое или интересное решение, но для этой области действия оно работает и позволяет быстро перейти к следующей проблеме.

Ответ 3

Ничего себе, похоже, горячий вопрос: p Мое предложение:

' - '.join(filter(bool, (a, b)))

Что дает:

>>> ' - '.join(filter(bool, ('', '')))
''
>>> ' - '.join(filter(bool, ('1', '')))
'1'
>>> ' - '.join(filter(bool, ('1', '2')))
'1 - 2'
>>> ' - '.join(filter(bool, ('', '2')))
'2'

Очевидно, что None ведет себя как '' с этим кодом.

Ответ 4

Вот один из вариантов:

("%s - %s" if (a and b) else "%s%s") % (a,b)

EDIT: как указано в mgilson, этот код не смог бы с None лучшим способом (но менее читаемым):

"%s - %s" % (a,b) if (a and b) else (a or b)

Ответ 5

Я просто хотел предложить решение для токенов, переписанное как один вкладыш, используя format.

output = "{0} - {1}".format(a, b) if (a and b) else (a or b)

Ответ 6

Здесь много ответов:)

Два лучших ответа (производительность и чистый код в одной строке) - это ответы @icecrime и @Hoopdady

Оба варианта равны, единственная разница - производительность.

cases = [
 (None, 'testB'),
 ('', 'testB'),
 ('testA', 'testB'),
 ('testA', ''),
 ('testA', None),
 (None, None)
]

for case in cases: print '-'.join(filter(bool, case))
'testB'
'testB'
'testA-testB'
'testA'
'testA'

for case in cases: print '-'.join([x for x in case if x])
'testB'
'testB'
'testA-testB'
'testA'
'testA'

Итак, давайте сравним:)

import timeit

setup = '''
cases = [
  (None, "testB"),
  ("", "testB"),
  ("testA","testB"),
  ("testA", ""),
  ("testA", None),
  (None, None)
]
'''

print min(timeit.Timer(
  "for case in cases: '-'.join([x for x in case if x])", setup=setup
).repeat(5, 1000))
0.00171494483948

print min(timeit.Timer(
  "for case in cases: '-'.join(filter(bool, case))", setup=setup
).repeat(5, 1000))
0.00283288955688

Но, как сказал @mgilson, используя None вместо bool, поскольку функция в filter дает тот же результат и имеет довольно высокую производительность:

print min(timeit.Timer(
  "for case in cases: '-'.join(filter(None, case))", setup=setup
).repeat(5, 1000))
0.00154685974121

Итак, лучший результат - это ответ, полученный @icecrime с предложением от @mgilson:

'-'.join(filter(None, (a,b)))

Разница в производительности составляет миллисекунды на 1000 итераций (микросекунды на итерацию). Таким образом, эти два метода имеют совершенно равную производительность, и для практически любого проекта вы можете выбрать любой; Если ваш проект должен иметь лучшую производительность, учитывая микросекунды, вы можете следовать этому эталону:)

Ответ 7

Попробуйте следующее:

def myfunc(a,b):
    if not b:
        return a
    elif not a:
        return b
    else:
        return a+' - '+b

или

def myfunc(a,b):
    if a and b:
        return a+' - '+b
    else:
        return a or b

Ответ 8

Что-то питонское, читаемое и элегантное:

strings = string1, string2

'{0}{1}{2}'.format(
    # output first string if it not empty
    strings[0] if strings[0] else '',

    # join with hyphen if both strings are not empty    
    '-' if all(strings) else '',

    # output second string if it not empty
    strings[1] if strings[1] else ''
    )

И быстро тоже;)

Ответ 9

Я бы сделал это следующим образом:

def show_together(item1=None, item2=None, seperator='-'):
    return '%s%s%s' % (item1,seperator,item2) if item1 and item2 else item1 or item2



>>> show_together(1,1)
'1-1'

>>> show_together(1)
1

>>> show_together()
>>> show_together(4,4,'$')
'4$4'