假设我正在编写一个递归函数,希望将a传递list给缺少单个元素的函数,作为循环的一部分。这是一种可能的解决方案:
def Foo(input):
if len(input) == 0: return
for j in input:
t = input[:]
t.remove(j)
Foo(t)
Run Code Online (Sandbox Code Playgroud)
有没有一种方法可以滥用slice运算符来传递列表减去元素,j而无需显式复制列表并从中删除项目?
那这个呢?
for i in range(len(list_)):
Foo(list_[:i] + list_[i+1:])
Run Code Online (Sandbox Code Playgroud)
您仍在复制项目,尽管您i在复制时忽略了索引处的元素。
顺便说一句,您总是可以尝试避免覆盖内置名称,例如list附加下划线。
如果您的列表很小,我建议使用@satoru 的答案中的方法。
如果您的列表非常大,并且您想避免创建和删除列表实例的“混乱”,那么使用生成器怎么样?
import itertools as it
def skip_i(seq, i):
return it.chain(it.islice(seq, 0, i), it.islice(seq, i+1, None))
Run Code Online (Sandbox Code Playgroud)
这将跳过第 i 个元素的工作推入了 C 的内部itertools,因此这应该比用纯 Python 编写等效内容更快。
要在纯 Python 中完成此操作,我建议编写一个如下所示的生成器:
def gen_skip_i(seq, i):
for j, x in enumerate(seq):
if i != j:
yield x
Run Code Online (Sandbox Code Playgroud)
编辑:这是我的答案的改进版本,感谢下面评论中的@Blckknght。
import itertools as it
def skip_i(iterable, i):
itr = iter(iterable)
return it.chain(it.islice(itr, 0, i), it.islice(itr, 1, None))
Run Code Online (Sandbox Code Playgroud)
这比我原来的答案有很大的进步。我原来的答案只适用于可索引的东西,例如列表,但这对于任何可迭代的东西都可以正常工作,包括迭代器!它从可迭代对象中创建一个显式迭代器,然后(在“链”中)提取第一个i值,并在提取所有剩余值之前仅跳过一个值。
非常感谢@Blckknght!