在满足条件的两个相邻列表元素之间插入元素
在Python中,有什么简单的方法可以在满足某个条件的两个元素之间插入一个新元素呢?
比如说,调用一个函数像这样:
insert_between([1,2,3,4,7,8,9,15,16], 0, lambda x,y: x + 1 != y)
应该得到这样的结果:
[1,2,3,4,0,7,8,9,0,15,16]
有没有比逐个遍历并添加到第二个列表的方式更好的方法呢?
相关问题:
3 个回答
2
可以很简单地使用lambda函数和reduce来实现。
l=[1, 2, 3, 4, 7, 8, 9, 15, 16]
f = lambda l, i: l+[0,i] if l and l[-1]+1!=i else l+[i]
print reduce(f, l, [])
[1, 2, 3, 4, 0, 7, 8, 9, 0, 15, 16]
2
@katrielalex 提出的方案可能是最有效的做法,无论是从时间还是内存的角度来看。这里有一个类似的版本,它返回的是一个新的列表,而不是一个迭代器。
def insert_between(items, insert_item, compare):
result = items[:1]
prev = result[0]
for item in items[1:]:
if not compare(prev, item):
result.append(insert_item)
result.append(item)
prev = item
return result
如果你需要在原地修改一个列表,而不想使用额外的内存来存储两个列表,你可以使用切片赋值。我个人不太喜欢在这里使用索引和 while 循环,但因为我们是在修改列表,所以在这种情况下,这似乎是最简单的方法。这种方法会比较慢,尤其是对于大列表来说,但在处理大列表时,你也能节省最多的内存。
def insert_between(items, insert_item, compare):
i = 1
while i < len(items):
if not compare(items[i-1], items[i]):
items[i:i] = [insert_item]
i += 1
i += 1
return items
11
>>> def insert_between(iterable, fill, cond):
... iterable = iter(iterable)
... prev = next(iterable)
... yield prev
... for cur in iterable:
... if cond(prev, cur):
... yield fill
... yield cur
... prev = cur
...
>>>
>>> list(insert_between([1,2,3,4,7,8,9,15,16], 0, lambda x,y: x + 1 != y))
[1, 2, 3, 4, 0, 7, 8, 9, 0, 15, 16]
这个方法的效率差不多是你能得到的最高了,因为你无论如何都得遍历一遍列表,而这个方法只需要遍历一次。注意,它是一个生成器,所以如果你想一次性获取所有的值,就需要把它转换成列表。