Reputation: 195
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"]
Upvotes: 4
Views: 892
Reputation: 82899
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, e.g. 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 e.g. 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. E.g., 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']
Upvotes: 1
Reputation: 106553
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']
Upvotes: 4
Reputation: 12015
>>> sorted(list_one, key=lambda x: [i for i,e in enumerate(list_two) if e in x][0])
['a78', '67b', 'c11']
Upvotes: -1
Reputation: 3822
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"]
Upvotes: 3