在满足条件的两个相邻列表元素之间插入元素

时间:2022-12-09 14:09:06

In python, what's a clean way to insert an element between any two elements that meet a condition?

在python中,在满足条件的任何两个元素之间插入元素的干净方法是什么?

A call like:

像这样的电话:

insert_between([1,2,3,4,7,8,9,15,16], 0, lambda x,y: x + 1 != y)

should produce:

应该产生:

[1,2,3,4,0,7,8,9,0,15,16]

Is there a better way than to iterate and append to second list?

有没有比迭代和附加到第二个列表更好的方法?

3 个解决方案

#1


10  

>>> 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]

This is pretty much as efficient as you'll get, because you're going to have to make one pass through the list anyway and this makes only one pass. Notice that it is a generator, so you need to cast it to a list if you need all the values at once.

这非常有效,因为你无论如何都必须通过列表,这只能通过一次。请注意,它是一个生成器,因此如果您需要一次所有值,则需要将其强制转换为列表。

#2


2  

@katrielalex's version is probably the most efficient way to do it, both in terms of time and memory. Here is a similar version that returns a new list rather than an iterator.

@ 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

If you need to modify a list in place, without using the memory for two lists, you can do slice assignment. I kind of dislike using the index and while loop here, but since we're modifying the list as we go, it seems the simplest way in this case. This will be slower, especially with large lists, but you'll also save the most memory with large lists.

如果需要修改列表,而不使用两个列表的内存,则可以执行切片分配。我有点不喜欢在这里使用索引和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

#3


1  

Can be done easily using lambda function and reduce

可以使用lambda函数轻松完成并减少

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]

#1


10  

>>> 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]

This is pretty much as efficient as you'll get, because you're going to have to make one pass through the list anyway and this makes only one pass. Notice that it is a generator, so you need to cast it to a list if you need all the values at once.

这非常有效,因为你无论如何都必须通过列表,这只能通过一次。请注意,它是一个生成器,因此如果您需要一次所有值,则需要将其强制转换为列表。

#2


2  

@katrielalex's version is probably the most efficient way to do it, both in terms of time and memory. Here is a similar version that returns a new list rather than an iterator.

@ 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

If you need to modify a list in place, without using the memory for two lists, you can do slice assignment. I kind of dislike using the index and while loop here, but since we're modifying the list as we go, it seems the simplest way in this case. This will be slower, especially with large lists, but you'll also save the most memory with large lists.

如果需要修改列表,而不使用两个列表的内存,则可以执行切片分配。我有点不喜欢在这里使用索引和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

#3


1  

Can be done easily using lambda function and reduce

可以使用lambda函数轻松完成并减少

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]