【问题标题】:Using itertools groupby to sort lists and merge dictionaries使用 itertools groupby 对列表进行排序和合并字典
【发布时间】:2017-02-15 20:08:47
【问题描述】:

我希望使用 python intertools groupby 来创建一个将小列表分组到更大列表中的函数。我开始的是具有以下结构的不同数据点的列表(称为 sortedData)

[
  [location, date, {item:quantity}],
  [location2, date, {item2:quantity2}],
  ...
]

我正在尝试对它们进行分组,以便每个位置/日期组合都有一个包含所有项目和数量的字典,并且这些列表按位置分组。这是一个例子:

[
  [
    [Maine, 01062016, {apple:5, orange:2}],
    [Maine, 02042016,{apple:3, peach:2}]
  ],
  [
    [Vermont, 01032016, {peach:3}]
  ]
]

到目前为止,我所拥有的是这段代码,但我无法理解如何使用创建的组,因为它不是可迭代的项目。现在它给出了一个空白列表,虽然它似乎应该附加一些东西

def compileData(sortedData):    
    from itertools import groupby
    for key, locationGroup in groupby(sortedData, lambda x: x[0]):
        locationList=[]
        bigList=[]
        for date in locationGroup:
            locationList.append(date)
        locationList.append(locationGroup)
        for key, bigList in groupby(locationGroup, lambda x: x[1]):
            datePlace=[key[0],key[1],{}]
            for date in locationGroup:
                datePlace[2]=dict(list(date[2].items())+list(datePlace[2].items()))
                bigList.append(datePlace)
        return bigList  

让我知道您的想法,如果您对如何解决此问题有任何更好的想法,请告诉我。我用recursivley写了它,但是我使用它的文件太长了,所以它太慢了。

【问题讨论】:

  • 您能否添加一个示例,说明您希望得到什么样的输出?
  • “使用 itertools groupby 进行排序” - itertools.groupby 不进行排序。如果您需要对事物进行排序,itertools.groupby 将无法帮助您。它有助于处理已排序的数据,但需要其他东西来确保数据已排序。
  • 嗨,米奇,第二个块引用有我正在寻找的输出。 (即列表列表的列表)
  • 我认为组实际上是一个更准确的词来形容我正在做的事情。我在帖子里改了。感谢您指出这一点。
  • 您能提供一个输入样本吗? (sortedData 是什么样的?)

标签: python list dictionary group-by itertools


【解决方案1】:

我认为这是你想要的:

from itertools import groupby
from operator import itemgetter

def update_with_ignore(a, b):
    '''Copy only new entries from B to A'''
    for k,v in b.items():
        a.setdefault(k,v)

def compileData(sortedData):
    result = []
    sortedData = sorted(sortedData, key=itemgetter(0,1))
    for location, group in groupby(sortedData, key=itemgetter(0)):
        l = []
        for date, group in groupby(group, key=itemgetter(1)):
            d = {}
            for datum in group:
                update_with_ignore(d, datum[2])
            l.append([location, date, dict(d)])
        result.append(l)
    return result


in_data = [
    ["Maine", "01062016", {"apple":5}],
    ["Maine", "02042016", {"apple":3}],
    ["Maine", "01062016", {"orange":2}],
    ["Vermont", "01032016", {"peach":3}],
    ["Maine", "02042016", {"peach":2}],
]
out_data = compileData(in_data)
assert out_data == [
 [['Maine', '01062016', {'apple': 5, 'orange': 2}],
  ['Maine', '02042016', {'apple': 3, 'peach': 2}]],
 [['Vermont', '01032016', {'peach': 3}]]]

in_data = [
    ["Maine", "01062016", {"apple":5}],
    ["Maine", "01062016", {"apple":4}],
    ["Maine", "02042016", {"apple":3}],
]
out_data = compileData(in_data)
assert out_data == [
 [['Maine', '01062016', {'apple': 5}],
  ['Maine', '02042016', {'apple': 3}]]]

【讨论】:

  • 真的很好。 @Amelia,dict 不是一个更好的数据结构吗?
  • Kelvin,你的意思是有这样的字典吗{(location:date):{item:value}}
  • 还有 Rob,非常感谢。我确实喜欢列表理解,老实说不熟悉集合、运算符、pprint 或断言,所以我将坚持你的第二个解决方案。谢谢!
  • @Robᵩ 我将它与我的数据文件一起使用,我收到一个错误:表示无法连接关于以下导入代码的 str 和 int 变量:` 630 result = Counter()` 631对于 elem,在 self.items() 中计数: --> 632 newcount = count + other[elem] 633 if newcount > 0: 634 result[elem] = newcount 这是指什么?你能说出这里连接的是什么吗?
  • @AmeliaMcClure - 我猜你的字典值之一是一个字符串。我的代码只有在所有字典值都是整数时才有效。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-02-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-02-20
  • 1970-01-01
相关资源
最近更新 更多