简体   繁体   中英

Insert an element between two adjacent list elements which meet a condition

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

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?

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

@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.

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.

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

Can be done easily using lambda function and 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]

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM