2017-03-02 48 views
5

我有一個詞典列表,我想循環分類。如何基於某些標準「循環」一個迭代器?

sample = [ 
    {'source': 'G', '"serial"': '0'}, 
    {'source': 'G', '"serial"': '1'}, 
    {'source': 'G', '"serial"': '2'}, 
    {'source': 'P', '"serial"': '30'}, 
    {'source': 'P', '"serial"': '0'}, 
    {'source': 'P', '"serial"': '1'}, 
    {'source': 'P', '"serial"': '2'}, 
    {'source': 'P', '"serial"': '3'}, 
    {'source': 'T', '"serial"': '2'}, 
    {'source': 'T', '"serial"': '3'} 
] 

我想這樣的結果:

sample_solved = [ 
    {'source': 'G', '"serial"': '0'}, 
    {'source': 'P', '"serial"': '30'}, 
    {'source': 'T', '"serial"': '2'}, 
    {'source': 'G', '"serial"': '1'}, 
    {'source': 'P', '"serial"': '1'}, 
    {'source': 'T', '"serial"': '3'}, 
    {'source': 'G', '"serial"': '2'}, 
    {'source': 'P', '"serial"': '0'}, 
    {'source': 'P', '"serial"': '2'}, 
    {'source': 'P', '"serial"': '3'} 
] 

我解決了它是如下的方式:

def roundrobin(*iterables): 
    # took from here https://docs.python.org/3/library/itertools.html#itertools-recipes 

    "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)) 

def solve(): 
    items_by_sources = collections.defaultdict(list) 

    for item in sample2: 
     items_by_sources[item["source"]].append(item) 

    t, p, g = items_by_sources.values() 

    print(list(roundrobin(t, p, g))) 

使用Python的defaultdict分離由源項目,然後使用循環解決方案我從Python的文檔中獲得。

但是,該解決方案,並不能覆蓋所有的情況下,例如t, p, g = items_by_sources.values()將打破當一個源丟失或新源已被添加。

我怎樣才能讓一個解決方案,覆蓋更多的優勢情況下,使該解決方案Python的?

回答

2

下面是使用itertools.groupby()您輸入分配到相應的組的解決方案:

from itertools import groupby 

def grouprobin(iterable, key): 
    groups = [list(g) for k, g in groupby(iterable, key)] 
    while groups: 
     group = groups.pop(0) 
     yield group.pop(0) 
     if group: 
      groups.append(group) 

因爲這樣groupby()作品,在roundrobin()版本巧妙地利用迭代器你的文檔了不

  1. 集團通過可迭代key

  2. :非常有幫助的,所以我的方式,是希望能更容易執行重寫它
  3. 雖然你仍然有組左起:

    1. 從組列表中的前流行音樂第一組

    2. 流行從該組的第一個項目,併產生了。

    3. 如果仍有組中的項目,追加它回到列表的末尾。

這是在行動:

>>> sample_solved = list(grouprobin(sample, key=lambda d: d['source'])) 
>>> from pprint import pprint 
>>> pprint(sample_solved) 
[{'"serial"': '0', 'source': 'G'}, 
{'"serial"': '30', 'source': 'P'}, 
{'"serial"': '2', 'source': 'T'}, 
{'"serial"': '1', 'source': 'G'}, 
{'"serial"': '0', 'source': 'P'}, 
{'"serial"': '3', 'source': 'T'}, 
{'"serial"': '2', 'source': 'G'}, 
{'"serial"': '1', 'source': 'P'}, 
{'"serial"': '2', 'source': 'P'}, 
{'"serial"': '3', 'source': 'P'}] 

grouprobin()版本以上假定您的列表已經排序。如果不是,就需要進行排序它的分組之前:

def grouprobin(iterable, key): 
    groups = [list(g) for k, g in groupby(sorted(iterable, key=key), key)] 
    while groups: 
     group = groups.pop(0) 
     yield group.pop(0) 
     if group: 
      groups.append(group)