「より良い」をより速く、エレガントで読みやすいものとして理解してください。
null かそうでないかの 2 つの文字列 (a
と) があります。b
そして、両方がnullでない場合にのみ、ハイフンで区切って連結したい:
a - b
a
(b が null の場合)
b
(a はヌル)
「より良い」をより速く、エレガントで読みやすいものとして理解してください。
null かそうでないかの 2 つの文字列 (a
と) があります。b
そして、両方がnullでない場合にのみ、ハイフンで区切って連結したい:
a - b
a
(b が null の場合)
b
(a はヌル)
# 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% の確率で速くなることがわかりました。したがって、それらが基本的に同等であることを示しています。
次のような単純なものはどうですか:
# 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
編集: このスレッドには興味深い解決策がたくさんあります。このソリューションを選択したのは、少なくとも実装に関しては、読みやすさと迅速さを重視していたからです。これは、最もスケーラブルで興味深いソリューションではありませんが、この範囲では機能し、すぐに次の問題に進むことができます。
うわー、ホットな質問のようです: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
のように動作します。''
ここに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)
を使用してワンライナーとして書き直された toxotes のソリューションを提供したかっただけformat
です。
output = "{0} - {1}".format(a, b) if (a and b) else (a or b)
ここにはたくさんの答えがあります:)
@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 を使用すると、同じ結果が得られ、パフォーマンスが大幅に向上します。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 回あたりのミリ秒 (反復あたりのマイクロ秒) です。したがって、これら 2 つの方法のパフォーマンスはまったく同じであり、ほぼすべてのプロジェクトでいずれかを選択できます。マイクロ秒を考慮して、プロジェクトのパフォーマンスを向上させる必要がある場合は、このベンチマークに従うことができます:)
これを試して:
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
パイソン的で読みやすくエレガントなもの:
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 ''
)
そして速すぎる;)
私は次のようにします:
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'