有没有像"iterate iterable if it has elements, else ..."这样的结构?
Is there a construct like "iterate iterable if it has elements, else ..."?
是否有更紧凑的方法来迭代具有元素的可迭代对象,或者如果没有元素则执行其他操作?
我的"problem"在Python,但我也对其他语言感兴趣。
目前我先测试元素个数:
In [1]: l=[]
In [2]: if l:
...: for e in l:
...: print(e)
...: else:
...: print("else")
...:
else
In [2]: for e in []:
...: print(e)
...: else:
...: print("else")
...:
else
但是它的"suite"(块)也在迭代完成时执行:
In [1]: for e in [1,2,3]:
...: print(e)
...: else:
...: print("else")
...:
1
2
3
else
我意识到这里没有太多收获(一行和缩进级别),但我很好奇是否存在这样的东西。
大多数时候你只是测试长度并提前退出:
if not l:
# empty case
return # or raise exception
无论如何,因为迭代不会在空列表上发生,下面的也足够了,不需要else
:
if not l:
# empty case
for i in l:
# only ever executed if there are any elements
for ... else
套件仅对提前退出 的循环有用; else
套件针对 完成 的所有循环执行。如果使用 break
,则跳过 else
。这使得它不适合检测空序列,因为在没有 break
语句的情况下,无论元素数量如何,对这些序列的迭代都会成功完成。
既然你要求其他语言,这里是Squeak/Pharo Smalltalk,因为范式足够接近Python:
你会这样写:
aCollection
ifEmpty: [Transcript cr; show: 'else']
ifNotEmpty: [aCollection do: [:each | Transcript cr; show: each printString]].
您也可以在 Collection 中创建一个新方法:
ifNotEmptyDo: aBlock elseDo: elseBlock
self isEmpty ifTrue: [^elseBlock value].
^self do: aBlock
然后像这样使用它:
aCollection
ifNotEmptyDo: [:each | Transcript cr; show: each printString]
elseDo: [Transcript cr; show: 'else'].
注意 isEmpty 默认定义为 ^self size = 0
,这对于可能的惰性或无限集合来说是一种异端……所以我提出这个新定义:
isEmpty
self do: [:each |^false].
^true
只是为了看看测试空性或执行循环或多或少是相同的任务;)
结论,在Smalltalk中语法糖的水平很低
块闭包启用不同的、有条件的或重复的评估。
因此,所有的构造,如分支和循环以及它们的组合,都只是以块闭包为参数的普通消息,您可以随意添加自己的构造。
这个设施经常被过度选择器滥用,以获得非常小的附加值,因此对新构造的需求应该始终与维护成本保持平衡(更多的方法来实施、测试和为新手学习等......) .让我们记住:“小即是美”。
是否有更紧凑的方法来迭代具有元素的可迭代对象,或者如果没有元素则执行其他操作?
我的"problem"在Python,但我也对其他语言感兴趣。
目前我先测试元素个数:
In [1]: l=[]
In [2]: if l:
...: for e in l:
...: print(e)
...: else:
...: print("else")
...:
else
In [2]: for e in []:
...: print(e)
...: else:
...: print("else")
...:
else
但是它的"suite"(块)也在迭代完成时执行:
In [1]: for e in [1,2,3]:
...: print(e)
...: else:
...: print("else")
...:
1
2
3
else
我意识到这里没有太多收获(一行和缩进级别),但我很好奇是否存在这样的东西。
大多数时候你只是测试长度并提前退出:
if not l:
# empty case
return # or raise exception
无论如何,因为迭代不会在空列表上发生,下面的也足够了,不需要else
:
if not l:
# empty case
for i in l:
# only ever executed if there are any elements
for ... else
套件仅对提前退出 的循环有用; else
套件针对 完成 的所有循环执行。如果使用 break
,则跳过 else
。这使得它不适合检测空序列,因为在没有 break
语句的情况下,无论元素数量如何,对这些序列的迭代都会成功完成。
既然你要求其他语言,这里是Squeak/Pharo Smalltalk,因为范式足够接近Python:
你会这样写:
aCollection
ifEmpty: [Transcript cr; show: 'else']
ifNotEmpty: [aCollection do: [:each | Transcript cr; show: each printString]].
您也可以在 Collection 中创建一个新方法:
ifNotEmptyDo: aBlock elseDo: elseBlock
self isEmpty ifTrue: [^elseBlock value].
^self do: aBlock
然后像这样使用它:
aCollection
ifNotEmptyDo: [:each | Transcript cr; show: each printString]
elseDo: [Transcript cr; show: 'else'].
注意 isEmpty 默认定义为 ^self size = 0
,这对于可能的惰性或无限集合来说是一种异端……所以我提出这个新定义:
isEmpty
self do: [:each |^false].
^true
只是为了看看测试空性或执行循环或多或少是相同的任务;)
结论,在Smalltalk中语法糖的水平很低
块闭包启用不同的、有条件的或重复的评估。
因此,所有的构造,如分支和循环以及它们的组合,都只是以块闭包为参数的普通消息,您可以随意添加自己的构造。
这个设施经常被过度选择器滥用,以获得非常小的附加值,因此对新构造的需求应该始终与维护成本保持平衡(更多的方法来实施、测试和为新手学习等......) .让我们记住:“小即是美”。