简体   繁体   中英

Sorting list based on order of substrings in another list

I have two lists of strings.

list_one = ["c11", "a78", "67b"]
list_two = ["a", "b", "c"]

What is the shortest way of sorting list_one using strings from list_two to get the following output?

["a78", "67b", "c11"]

Edit 1: There is a similar question Sorting list based on values from another list? , but in that question he already has the list of required indexes for resulting string, while here I have just the list of substrings.

Edit 2: Since the example of list above might be not fully representative, I add another case.

list_one is ["1.cde.png", "1.abc.png", "1.bcd.png"] list_two is ["abc", "bcd", "cde"] . The output is supposed to be [ "1.abc.png", "1.bcd.png", "1.cde.png"]

If, for example, list_one is shorter than list_two, it should still work:

list_one is ["1.cde.png", "1.abc.png"] list_two is ["abc", "bcd", "cde"] The output is supposed to be [ "1.abc.png", "1.cde.png"]

key = {next((s for s in list_one if v in s), None): i for i, v in enumerate(list_two)}
print(sorted(list_one, key=key.get))

This outputs:

['a78', '67b', 'c11']

Try this

list_one = ["c11", "a78", "67b"]
list_two = ["a", "b", "c"]

[x for y in list_two for x in list_one if y in x]

Output :

["a78", "67b", "c11"]

Assuming that each item in list_one contains exactly one of the characters from list_two , and that you know the class of those characters, eg letters, you can extract those using a regex and build a dictionary mapping the characters to the element. Then, just look up the correct element for each character.

>>> list_one = ["c11", "a78", "67b"]
>>> list_two = ["a", "b", "c"]
>>> d = {re.search("[a-z]", s).group(): s for s in list_one}
>>> list(map(d.get, list_two))
['a78', '67b', 'c11']
>>> [d[c] for c in list_two]
['a78', '67b', 'c11']

Other than the other approaches posted so far, which all seem to be O(n²), this is only O(n).

Of course, the approach can be generalized to eg more than one character, or characters in specific positions of the first string, but it will always require some pattern and knowledge about that pattern. Eg, for your more recent example:

>>> list_one = ["1.cde.png", "1.abc.png", "1.bcd.png"]
>>> list_two = ["abc", "cde"]
>>> d = {re.search("\.(\w+)\.", s).group(1): s for s in list_one}
>>> d = {s.split(".")[1]: s for s in list_one}  # alternatively without re
>>> [d[c] for c in list_two if c in d]
['1.abc.png', '1.cde.png']
>>> sorted(list_one, key=lambda x: [i for i,e in enumerate(list_two) if e in x][0])
['a78', '67b', 'c11']

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