Merge two or more lists with given order of merging

前端 未结 2 1556
悲哀的现实
悲哀的现实 2020-12-10 16:36

On start I have 2 lists and 1 list that says in what order I should merge those two lists. For example I have first list equal to [a, b, c] and second list equa

相关标签:
2条回答
  • 2020-12-10 17:13

    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']
    
    0 讨论(0)
  • 2020-12-10 17:18

    You could create iterators from those lists, loop through the ordering list, 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']
    

    It's possible to 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 ordering list contains strings, floats, or any other objects that can't be used as list indexes, use a 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 use integers as dictionary keys as well.


    Alternatively, you could remove elements from the left side of each of the original 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 would expect the first approach to be more efficient (list.pop(0) is slow).

    0 讨论(0)
提交回复
热议问题