Вопрос

Suppose I have a configuration dictionary:

config = {'A': 3, 'B': 4, 'C': 2}

How do I flat distribute (intersperse) the list like this: (append one by one into result list still end of all config)

result = ['A', 'B', 'C', 'A', 'B', 'C', 'A', 'B', 'B']

Another example case:

config = {'A': 3, 'B': 1}
result = ['A', 'B', 'A', 'A']

config = {'A': 2, 'B': 2}
result = ['A', 'B', 'A', 'B']
Это было полезно?

Решение 2

from itertools import izip_longest as izip_l, chain
config = {'A': 3, 'B': 4, 'C': 2}

# Reconstruct the list of lists
expanded = [[k] * config[k] for k in config]

# Just zip them and ignore the None
print[item for item in chain.from_iterable(izip_l(*expanded)) if item]

If the count is too big and if you are worried about the performance and the memory consumed, you can use repeat instead of reconstructing the list of lists, like this

from itertools import izip_longest as izip_l, chain, repeat
expanded = [repeat(k, config[k]) for k in config]

Rest all are the same

Другие советы

You can use the itertools recipe roundrobin for this:

from itertools import cycle, islice

def roundrobin(*iterables):
    "roundrobin('ABC', 'D', 'EF') --> A D E B F C"
    # Recipe credited to George Sakkis
    pending = len(iterables)
    nexts = cycle(iter(it).next for it in iterables)
    while pending:
        try:
            for next in nexts:
                yield next()
        except StopIteration:
            pending -= 1
            nexts = cycle(islice(nexts, pending))

result = list(roundrobin(*(k * v for k, v in sorted(config.items()))))

Without any extra lib

main_config = {'A': 3, 'C': 4, 'B': 2}
config = main_config
list = []
for lp in range(max(config.values())):
    for key in config.keys():
        val = config.get(key)
        if val != 0:
            list.append(key)
            config.update({key:val-1})
print list

Output:

['A', 'C', 'B', 'A', 'C', 'B', 'A', 'C', 'C']
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top