从python中的列表字典中删除公共元素

从python中的列表字典中删除公共元素,python,list,dictionary,Python,List,Dictionary,我有一个列表词典,列表中包含如下词典: my_dict = { 'list1': [{'catch': 100, 'id': '1'}, {'catch': 101, 'id': '2'}, {'catch': 50, 'id': '1'}], 'list2': [{'catch': 189, 'id': '1'}, {'catch': 120, 'id': '12'}], 'list3': [{'catch': 140, 'id': '1'}, {'catch': 1

我有一个列表词典,列表中包含如下词典:

my_dict = {
'list1': [{'catch': 100, 'id': '1'}, {'catch': 101, 'id': '2'}, 
          {'catch': 50, 'id': '1'}], 
'list2': [{'catch': 189, 'id': '1'}, {'catch': 120, 'id': '12'}], 
'list3': [{'catch': 140, 'id': '1'}, {'catch': 10, 'id': '100'}]
}
删除具有commin'id'值的列表项并将其存储在单独的列表中,最适合的方式是什么?所以输出应该是这样的:

my_dict = {
'list1': [{'catch': 101, 'id': '2'}], 
'list2': [{'catch': 120, 'id': '12'}], 
'list3': [ {'catch': 10, 'id': '100'}],
'list4': [{'catch': 100, 'id': '1'}, , {'catch': 50, 'id': '1'}, 
          {'catch': 189, 'id': '1'}, {'catch': 140, 'id': '1'}]
}
>>> import itertools
>>> { k: [d['catch'] for d in v] for k, v in itertools.groupby(sorted(itertools.chain(*my_dict.itervalues()), key=lambda d: d['id']), lambda d: d['id']) }
{'1': [100, 50, 140, 189], '2': [101], '100': [10], '12': [120]}
在我的程序中,我有7个类似的列表,如果其中两个或多个列表中出现了“id”,我想将具有该“id”的项目的所有外观存储在第8个列表中,以便进一步处理

关于,, 芬努托法

>>> get_id = operator.itemgetter("id")
>>> flattened_dict = itertools.chain.from_iterable(my_dict.values())
>>> groups = itertools.groupby(sorted(flattened_dict, key=get_id), get_id)
>>> {k: list(v) for k, v in groups}
{'1': [{'catch': 100, 'id': '1'},
  {'catch': 50, 'id': '1'},
  {'catch': 140, 'id': '1'},
  {'catch': 189, 'id': '1'}],
 '100': [{'catch': 10, 'id': '100'}],
 '12': [{'catch': 120, 'id': '12'}],
 '2': [{'catch': 101, 'id': '2'}]}
说明:

  • get\u id
    是一个函数,它接受对象
    x
    并返回
    x[“id”]
  • flatted_dict
    只是一个可在所有列表上使用的函数(即,连接
    my_dict的所有
    .values()
  • 现在,我们使用键函数“获取id”(即,按id排序)对结果进行排序,并按id对结果进行分组
这基本上是可行的,因为
itertools.groupby
非常棒

说明:

  • get\u id
    是一个函数,它接受对象
    x
    并返回
    x[“id”]
  • flatted_dict
    只是一个可在所有列表上使用的函数(即,连接
    my_dict的所有
    .values()
  • 现在,我们使用键函数“获取id”(即,按id排序)对结果进行排序,并按id对结果进行分组

这基本上是可行的,因为
itertools.groupby
非常棒。

下面是一个例子:

my_dict = {
'list1': [{'catch': 100, 'id': '1'}, {'catch': 101, 'id': '2'}, 
      {'catch': 50, 'id': '1'}], 
'list2': [{'catch': 189, 'id': '1'}, {'catch': 120, 'id': '12'}], 
'list3': [{'catch': 140, 'id': '1'}, {'catch': 10, 'id': '100'}]
}

from itertools import groupby

sub = {}
for k in my_dict:
 for kk, g in groupby( my_dict[k], lambda v: v["id"] ):
   if not kk in sub:
    sub[kk] = []
   sub[kk] = sub[kk] + list( g )

print sub

{'1': [{'catch': 100, 'id': '1'}, {'catch': 50, 'id': '1'}, {'catch': 140, 'id': '1'}, {'catch': 189, 'id': '1'}], '12': [{'catch': 120, 'id': '12'}], '100': [{'catch': 10, 'id': '100'}], '2': [{'catch': 101, 'id': '2'}]}

大致如下:

my_dict = {
'list1': [{'catch': 100, 'id': '1'}, {'catch': 101, 'id': '2'}, 
      {'catch': 50, 'id': '1'}], 
'list2': [{'catch': 189, 'id': '1'}, {'catch': 120, 'id': '12'}], 
'list3': [{'catch': 140, 'id': '1'}, {'catch': 10, 'id': '100'}]
}

from itertools import groupby

sub = {}
for k in my_dict:
 for kk, g in groupby( my_dict[k], lambda v: v["id"] ):
   if not kk in sub:
    sub[kk] = []
   sub[kk] = sub[kk] + list( g )

print sub

{'1': [{'catch': 100, 'id': '1'}, {'catch': 50, 'id': '1'}, {'catch': 140, 'id': '1'}, {'catch': 189, 'id': '1'}], '12': [{'catch': 120, 'id': '12'}], '100': [{'catch': 10, 'id': '100'}], '2': [{'catch': 101, 'id': '2'}]}

考虑将数据重组为以下内容:

my_dict = {
'list1': [{'catch': 101, 'id': '2'}], 
'list2': [{'catch': 120, 'id': '12'}], 
'list3': [ {'catch': 10, 'id': '100'}],
'list4': [{'catch': 100, 'id': '1'}, , {'catch': 50, 'id': '1'}, 
          {'catch': 189, 'id': '1'}, {'catch': 140, 'id': '1'}]
}
>>> import itertools
>>> { k: [d['catch'] for d in v] for k, v in itertools.groupby(sorted(itertools.chain(*my_dict.itervalues()), key=lambda d: d['id']), lambda d: d['id']) }
{'1': [100, 50, 140, 189], '2': [101], '100': [10], '12': [120]}
您尚未描述数据所代表的内容,因此这可能不适合您。但所使用的工具(
chain
groupby
,来自
itertools
)至少应该能为您提供一些想法


编辑:我在测试中无意中使用了问题的示例答案。通过将排序添加到
groupby

的输入中,可以修复此问题。请考虑将数据重组为以下内容:

my_dict = {
'list1': [{'catch': 101, 'id': '2'}], 
'list2': [{'catch': 120, 'id': '12'}], 
'list3': [ {'catch': 10, 'id': '100'}],
'list4': [{'catch': 100, 'id': '1'}, , {'catch': 50, 'id': '1'}, 
          {'catch': 189, 'id': '1'}, {'catch': 140, 'id': '1'}]
}
>>> import itertools
>>> { k: [d['catch'] for d in v] for k, v in itertools.groupby(sorted(itertools.chain(*my_dict.itervalues()), key=lambda d: d['id']), lambda d: d['id']) }
{'1': [100, 50, 140, 189], '2': [101], '100': [10], '12': [120]}
您尚未描述数据所代表的内容,因此这可能不适合您。但所使用的工具(
chain
groupby
,来自
itertools
)至少应该能为您提供一些想法



编辑:我在测试中无意中使用了问题的示例答案。通过在
groupby

的输入中添加排序修复了此问题。也许是时候重新考虑您的数据结构了?@MartijnPieters,我完全同意这一点-发生这种情况的一个现实例子是从基于文档的数据库返回的对象列表atabase…dict键的意义是什么?我在回答中忽略了它们,因为它们似乎没有任何实际意义,但也许它们有…@MartijnPieters我同意,在看到这里的答案后,我将重新思考我的数据结构:)@Katrielex谢谢你的回答。这不完全是我的想法,但我将重新思考我的数据结构,并将使用类似于你的答案的东西。也许是时候重新思考你的数据结构了?@MartijnPieters,我完全同意这一点-发生这种情况的真实例子是从一个基于文档的数据库…dict键的意义是什么?我在回答中忽略了它们,因为它们似乎没有任何实际意义,但也许它们确实有…@MartijnPieters我同意,在看到这里的答案后,我将重新思考我的数据结构:)@Katrielex谢谢你的回答。这并不完全是我的想法,但我将重新思考我的数据结构,并将使用类似于您的回答的问题:如果您试图满足OP从现有列表中删除公共元素并将其放入其他列表中的需要,您如何保持代码高尔夫的答案?在您的解决方案中,列表1 2 3被重新编号。我不会将此代码称为高尔夫。我称之为“使用Python免费提供的强大工具”。回答你的问题,这会有点痛苦,但完全可行——但我不清楚OP到底想要什么,我很犹豫是否需要编写令人讨厌的代码。问:如果您试图满足OP的需要,从现有列表中删除常见元素并将其放入其他列表中,您如何保持代码高尔夫的答案?在您的解决方案中,列表1 2 3被重新编号。我不会将此代码称为高尔夫。我称之为“使用Python免费提供的强大工具”。回答您的问题,这会有点痛苦,但完全可行——但由于我不清楚OP到底想要什么,我对编写糟糕代码的需求犹豫不决。同意。所有数据实际上都是(
id,catch
)对的集合,您可以将其存储为
id:[catch]
的字典。您可能希望使用
链。从_iterable
可以惰性地迭代值。同意。所有数据实际上都是(
id,catch
)对的集合,您可以将其存储为
id:[catch]
的字典。您可能希望使用
链。从_iterable
可以惰性地迭代这些值。