将“更好”理解为更快,更优雅,更易读。
我有两个字符串(a
和b
),可以为null或不为。并且我希望只有当两者都不为空时才用连字符连接它们:
a - b
a
(如果b为空)
b
(其中a为null)
答案 0 :(得分:47)
# Concatenates a and b with ' - ' or Coalesces them if one is None
'-'.join([x for x in (a,b) if x])
修改强>
以下是此算法的结果(请注意,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])
''
*另请注意,在下面的帖子中,Rafael的评估仅在过滤方法的1000次迭代中显示出.0002秒的差异,可以推断出这样小的差异可能是由于可用系统资源的不一致在运行脚本时。我在几次迭代中运行了他的timeit实现,并发现任何一种算法在大约50%的时间内都会更快,也不会大幅度提高。因此显示它们基本相同。
答案 1 :(得分:35)
如此简单的事情:
# 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
编辑:这个帖子中有很多有趣的解决方案。我选择这个解决方案是因为我强调可读性和快速性,至少在实现方面。它不是最具扩展性或最有趣的解决方案,但是对于这个范围它可以工作,并且让我能够很快地转到下一个问题。
答案 2 :(得分:31)
' - '.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
与此代码的行为类似''
。
答案 3 :(得分:12)
这是一个选项:
("%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)
答案 4 :(得分:4)
我只是想使用format
将toxotes的解决方案重写为单行内容。
output = "{0} - {1}".format(a, b) if (a and b) else (a or b)
答案 5 :(得分:3)
这里有很多答案:)
两个最佳答案(性能和清晰的代码在一行中)是@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次迭代的毫秒数(每次迭代的微秒数)。因此,这两种方法具有完全相同的性能,对于几乎任何项目,您都可以选择任何一种;如果您的项目必须具有更好的性能,考虑到微秒,您可以遵循此基准:)
答案 6 :(得分:1)
这样做:
'-'.join(max(x,'') for x in [a,b] if x is not None)
答案 7 :(得分: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
答案 8 :(得分: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 ''
)
也很快;)
答案 9 :(得分: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'