Combine two or more lists with the specified merge order

At the beginning, I have 2 lists and 1 list, which says in what order I should combine these two lists. For example, I have the first list equal to [a, b, c] , and the second list is [d, e] and 'merging' equal to [0, 1, 0, 0, 1] .

This means: first create a combined list, I need to take an element from the first list, then the second, then first, then first, then the second ... And I get [a, d, b, c, e] . To solve this problem, I just used two β€œpointers” for the loop, but I was wondering if I could make this task more pythonic ... I tried to find some functions that could help me, but no real result.

+7
python
source share
2 answers

You can create iterators from these lists, iterate over the list of orders and call next on one of the iterators:

 i1 = iter(['a', 'b', 'c']) i2 = iter(['d', 'e']) # Select the iterator to advance: `i2` if `x` == 1, `i1` otherwise print([next(i2 if x else i1) for x in [0, 1, 0, 0, 1]]) # ['a', 'd', 'b', 'c', 'e'] 

You can generalize this solution to any number of lists, as shown below.

 def ordered_merge(lists, selector): its = [iter(l) for l in lists] for i in selector: yield next(its[i]) 
 In [4]: list(ordered_merge([[3, 4], [1, 5], [2, 6]], [1, 2, 0, 0, 1, 2])) Out[4]: [1, 2, 3, 4, 5, 6] 

If the order list contains strings, floats or any other objects that cannot be used as list indices, use the dictionary:

 def ordered_merge(mapping, selector): its = {k: iter(v) for k, v in mapping.items()} for i in selector: yield next(its[i]) 
 In [6]: mapping = {'A': [3, 4], 'B': [1, 5], 'C': [2, 6]} In [7]: list(ordered_merge(mapping, ['B', 'C', 'A', 'A', 'B', 'C'])) Out[7]: [1, 2, 3, 4, 5, 6] 

Of course, you can also use integers as dictionary keys.


Alternatively, you can remove the items on the left side of each of the source lists one by one and add them to the resulting list. Quick example:

 In [8]: A = ['a', 'b', 'c'] ...: B = ['d', 'e'] ...: selector = [0, 1, 0, 0, 1] ...: In [9]: [B.pop(0) if x else A.pop(0) for x in selector] Out[9]: ['a', 'd', 'b', 'c', 'e'] 

I expect the first approach will be more efficient ( list.pop(0) slow).

+14
source share

How about this

 list1 = ['a', 'b', 'c'] list2 = ['d', 'e'] options = [0,1,0,0,1] list1_iterator = iter(list1) list2_iterator = iter(list2) new_list = [next(list2_iterator) if option else next(list1_iterator) for option in options] print(new_list) # Output ['a', 'd', 'b', 'c', 'e'] 
+2
source share

All Articles