Effectively sort the list by sequence

Suppose I have two lists:

sequence = [25, 15, 20, 15, 25, 25]
l = [(25, 'banana'), 
     (25, 'apple'), 
     (25, 'pine'), 
     (20, 'soap'), 
     (15, 'rug'), 
     (15, 'cloud')]

I would like to sort the second list l in sequence. In the example, the number 25 appears several times, in this case it does not matter which tuple is in place if it has a value of 25. Lists will always have the same length.

My current approach is this:

r = list(range(len(sequence)))

for i, v in enumerate(sequence):
    for e in l:
        if e[0] == v:
            r[i] = e
            l.remove(e)
print(r)

Possible output:

[(25, 'banana'), (15, 'carpet'), (20, “soap”), (15, “cloud”) (25, “apple”) (25, “pine”)]

Do you see a better way to do this?

Thank you for your help!

Muff

+4
source share
4 answers

Jean's, pop ( O (n), , O (1), ).

>>> from collections import defaultdict
>>> supply = defaultdict(list)
>>> for k, v in l:
...     supply[k].append(v)
... 
>>> supply_iter = {k:iter(v) for k,v in supply.items()}
>>> [(k, next(supply_iter[k])) for k in sequence]
[(25, 'banana'), (15, 'rug'), (20, 'soap'), (15, 'cloud'), (25, 'apple'), (25, 'pine')]

next (None ).

+3

. ( )

sequence = [25, 15, 20, 15, 25, 25]
l = [(25, 'banana'),
     (25, 'apple'),
     (25, 'pine'),
     (20, 'soap'),
     (15, 'rug'),
     (15, 'cloud')]

from collections import defaultdict

d = defaultdict(list)
for i,n in l:
    d[i].append(n)

( ) list.pop, ( , , python ( / )):

result = [(i,d[i].pop()) for i in sequence]
print(result)

:

[(25, 'pine'), (15, 'cloud'), (20, 'soap'), (15, 'rug'), (25, 'apple'), (25, 'banana')]

, . , ( , , , , ):

result = [(i,d[i].pop(0)) for i in sequence]

:

[(25, 'banana'), (15, 'rug'), (20, 'soap'), (15, 'cloud'), (25, 'apple'), (25, 'pine')]
+5

Another option is to sort using a key function that will remove the elements used from sequence(this approach changes sequence, so a copy should be created if sequenceneeded later):

sequence = [25, 15, 20, 15, 25, 25]
l = [(25, 'banana'), 
     (25, 'apple'), 
     (25, 'pine'), 
     (20, 'soap'), 
     (15, 'rug'), 
     (15, 'cloud')]

def key_func(_tuple):
    idx = sequence.index(_tuple[0])
    sequence[idx] = None
    return idx

l.sort(key=key_func)

As Jared Gauguin said, if you need to save sequence, the following shell will help:

def get_key_func(sequence):
    sequence_copy = sequence[:]
    def key_func(_tuple):
        idx = sequence_copy.index(_tuple[0])
        sequence_copy[idx] = None
        return idx
    return key_func

l.sort(key=get_key_func(sequence))
+4
source

You can do this without setting up the array before the loop and without listing. I don't think this is faster, but it might be easier to understand:

r =[]

for val in sequence:
    for key, elem in l:
        if key == val:
            temp = (val, elem)
            r.append(temp)
            l.remove(temp)
            break # break the loop thru element to avoid having 2 elements of the same "key"
print(r)
+1
source

Source: https://habr.com/ru/post/1677714/


All Articles