20

「より良い」をより速く、エレガントで読みやすいものとして理解してください。

null かそうでないかの 2 つの文字列 (aと) があります。bそして、両方がnullでない場合にのみ、ハイフンで区切って連結したい:

a - b

a(b が null の場合)

b(a はヌル)

4

10 に答える 10

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

編集
このアルゴリズムの結果は次のとおりです(なしは「」と同じように機能することに注意してください):

>>> '-'.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])
''

*また、以下の彼の投稿での Rafael の評価では、フィルター メソッドの 1000 回の反復で 0.0002 秒の差しか示されていないことに注意してください。スクリプトの実行。彼の timeit 実装を何度か繰り返し実行したところ、どちらのアルゴリズムも約 50% の確率で速くなることがわかりました。したがって、それらが基本的に同等であることを示しています。

于 2013-03-12T12:21:32.880 に答える
36

次のような単純なものはどうですか:

# 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

編集: このスレッドには興味深い解決策がたくさんあります。このソリューションを選択したのは、少なくとも実装に関しては、読みやすさと迅速さを重視していたからです。これは、最もスケーラブルで興味深いソリューションではありませんが、この範囲では機能し、すぐに次の問題に進むことができます。

于 2013-03-12T12:21:47.630 に答える
31

うわー、ホットな質問のようです: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のように動作します。''

于 2013-03-12T12:45:17.387 に答える
12

ここに1つのオプションがあります:

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

編集:mgilsonが指摘しているように、このコードはNone'より良い方法で失敗します(ただし、読みにくい方法):

"%s - %s" % (a,b) if (a and b) else (a or b)
于 2013-03-12T12:19:09.677 に答える
4

を使用してワンライナーとして書き直された toxotes のソリューションを提供したかっただけformatです。

output = "{0} - {1}".format(a, b) if (a and b) else (a or b)
于 2013-03-12T18:28:58.740 に答える
3

ここにはたくさんの答えがあります:)

@icecrime と @Hoopdady の 2 つの最良の回答 (パフォーマンスとクリーンなコード) は、@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代わりにas を使用すると、同じ結果が得られ、パフォーマンスが大幅に向上します。boolfilter

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 回あたりのミリ秒 (反復あたりのマイクロ秒) です。したがって、これら 2 つの方法のパフォーマンスはまったく同じであり、ほぼすべてのプロジェクトでいずれかを選択できます。マイクロ秒を考慮して、プロジェクトのパフォーマンスを向上させる必要がある場合は、このベンチマークに従うことができます:)

于 2013-03-12T13:42:55.117 に答える
0

これを試して:

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
于 2013-03-12T12:21:56.307 に答える
0

パイソン的で読みやすくエレガントなもの:

strings = string1, string2

'{0}{1}{2}'.format(
    # output first string if it's 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's not empty
    strings[1] if strings[1] else ''
    )

そして速すぎる;)

于 2013-03-12T16:28:27.267 に答える
0

私は次のようにします:

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'
于 2013-03-12T16:30:38.760 に答える