【问题标题】:difference between dict(groupby) and groupby [duplicate]dict(groupby)和groupby之间的区别[重复]
【发布时间】:2013-10-07 04:46:15
【问题描述】:

我有一个这样的列表

[u'201003', u'200403', u'200803', u'200503', u'201303',
 u'200903', u'200603', u'201203', u'200303', u'200703', u'201103']

让我们将此列表称为“years_list”

当我按年分组时,

group_by_yrs_list = groupby(years_list, key = lambda year_month: year_month[:-2]) 
for k,v in group_by_yrs_list:
  print k, list(v)

我得到了想要的输出:

2010 [u'201003']
2004 [u'200403']
2008 [u'200803']
2005 [u'200503']
2013 [u'201303']
2009 [u'200903']
2006 [u'200603']
2012 [u'201203']
2003 [u'200303']
2007 [u'200703']
2011 [u'201103']

然后,我像这样稍微改变了我的实现,

  group_by_yrs_list = dict(groupby(years_list, key = lambda year_month: year_month[:-2]))
  for k,v in group_by_yrs_list.items():
    print k, list(v)

我刚刚添加了一个dict,但是输出不一样,

2003 []
2006 []
2007 []
2004 []
2005 []
2008 []
2009 []
2011 [u'201103']
2010 []
2013 []
2012 []

我不知道为什么。请帮我找出 dict 实际上在做什么。

(Python 2.7)

【问题讨论】:

  • 记住字典没有顺序。但至于为什么只有一个列表不为空,那就奇怪了
  • @Haidro:falstru 的回答应该能启发你。
  • @justhalf 哦,当然!
  • @TerryA,从 3.7 开始,注释已过时 - 字典按插入排序。

标签: python python-2.7


【解决方案1】:

尝试来自toolz 的非流式groupby 操作

$ pip install toolz
$ ipython

In [1]: from toolz import groupby

In [2]: years_list = [u'201003', u'200403', u'200803', u'200503', u'201303',
   ...:  u'200903', u'200603', u'201203', u'200303', u'200703', u'201103']

In [3]: get_year = lambda year_month: year_month[:-2]

In [4]: groupby(get_year, years_list)
Out[4]: 
{u'2003': [u'200303'],
 u'2004': [u'200403'],
 u'2005': [u'200503'],
 u'2006': [u'200603'],
 u'2007': [u'200703'],
 u'2008': [u'200803'],
 u'2009': [u'200903'],
 u'2010': [u'201003'],
 u'2011': [u'201103'],
 u'2012': [u'201203'],
 u'2013': [u'201303']}

【讨论】:

    【解决方案2】:

    groupby 产生成对的 (key, iterator-of-group)。如果您正在迭代第二对,则第一对的迭代器组已被消耗,因此您得到空列表。

    试试下面的代码:

    group_by_yrs_list = {year:list(grp) for year, grp in groupby(years_list, key=lambda year_month: year_month[:-2])}
    for k, v in group_by_yrs_list.items():
        print k, v
    

    【讨论】:

    • 这意味着所有分组的值都指向一个迭代器。我说的对吗?
    • @JohnPrawyn,是的。 itertools._grouper 对象共享一个迭代器。 (gbo->it)
    【解决方案3】:

    这里的问题是groupby 依次产生每个键和一个子迭代器:

    >>> for k, v in groupby(years_list, key = lambda year_month: year_month[:-2]):
    ...    print k, v
    2010 <itertools._grouper object at 0x801c68950>
    2004 <itertools._grouper object at 0x801bb3a90>
    2008 <itertools._grouper object at 0x801c68950>
    2005 <itertools._grouper object at 0x801bb3a90>
    2013 <itertools._grouper object at 0x801c68950>
    2009 <itertools._grouper object at 0x801bb3a90>
    2006 <itertools._grouper object at 0x801c68950>
    2012 <itertools._grouper object at 0x801bb3a90>
    2003 <itertools._grouper object at 0x801c68950>
    2007 <itertools._grouper object at 0x801bb3a90>
    2011 <itertools._grouper object at 0x801c68950>
    

    您需要将每个&lt;itertools._grouper object ...&gt; 转换为实际列表,然后再将其存储起来,因为groupby下一个 迭代会重置迭代器。如果你不这样做,只剩下一个有用的迭代器,所以当你打印字典的内容时,你会得到一个非空列表(它用完迭代器)。再次打印它,您将得到全空列表。

    关键是在迭代器还不错的时候列出它们(我看到其他几个人在示例代码方面击败了我,我更喜欢falsetru's variant)。

    【讨论】:

    • 来自docs:因为源是共享的,当groupby()对象被推进时,之前的组就不再可见了。因此,如果以后需要该数据,则应将其存储为列表。
    • 是的,基本相同的陈述,但更短更精确(我没有确切地说为什么旧的&lt;itertools._grouper object ...&gt;s 变得无用),但我怀疑那个版本可能会飞过 OP 的头顶 :-)
    • 你的答案很清楚,只是想添加一些对文档的引用。
    【解决方案4】:

    根据this answer,您可以这样做将其转换为dict

    group_by_yrs_list = dict((k,list(v)) for k,v in groupby(years_list, key=lambda x: x[:4]))
    

    这是因为groupby的输出是一个itertools.groupby对象,它是一种生成器,显然不能直接作为dict构造函数的参数使用。

    【讨论】:

      猜你喜欢
      • 2020-08-30
      • 2019-01-22
      • 2021-10-04
      • 2022-01-26
      • 2015-08-23
      • 2011-02-14
      • 2016-03-26
      • 1970-01-01
      • 2016-09-02
      相关资源
      最近更新 更多