I'm looking to create a list whose values alternate based on a set of known patterns. Note that there may not be an equal number of items with each prefix. (2 foos, 3 bars, 3 spams). My current solution is nasty gaggle that .pop()'s from lists built from common prefixes and appends to a new list.
prefix_patterns = ['foo','bar','spam']
inlist = ['fooABC','fooXYZ','barABC','barXYZ','spamABC','bar123','spamXYZ','spam123']
Desired output:
outlist = ['fooABC','barABC','spamABC','fooXYZ','barXYZ','spamXYZ','bar123','spam123']
Current solution (doesn't handle lists of differing lengths):
foos = [value for value in inlist if 'foo' in value]
bars = [value for value in inlist if 'bar' in value]
spams = [value for value in inlist if 'spam' in value]
while foos:
outlist.append(foos.pop())
outlist.append(bars.pop())
outlist.append(spams.pop())
For context: Looking to use this as a sort of throttling mechanism when making requests to 4 different servers.
Since you're using Python 2.x this would work:
# group by prefix first -> [['fooXX']['barXX']['spamXX']]
prefix_match = [[x for x in inlist if x.startswith(pre)] for pre in prefix_patterns]
outlist = [x for i in map(None,*prefix_match) for x in i if x]
The map built-in function will zip prefix_match together and pad with None if one of the lists is too short. Then you can simply flatten this list and exclude any None objects.
For Python 3.x you could replace the map function with itertools.zip_longest:
from itertools import zip_longest
prefix_match = [[x for x in inlist if x.startswith(pre)] for pre in prefix_patterns]
outlist = [x for i in zip_longest(*prefix_match) for x in i if x]
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With