Python:字典映射列表

时间:2019-11-20 04:06:33

标签: python json dictionary optimization mapping

我有一个来自JSON的10,000个字典的列表,如下所示:

my_list =
[
    {"id": 1, "val": "A"},
    {"id": 4, "val": "A"},
    {"id": 1, "val": "C"},
    {"id": 3, "val": "C"},
    {"id": 1, "val": "B"},
    {"id": 2, "val": "B"},
    {"id": 4, "val": "C"},
    {"id": 4, "val": "B"},
    .
    .
    .
    {"id": 10000, "val": "A"}
]

我希望我的输出是:

mapped_list =
[
    {"id": 1, "val": ["A", "B", "C"]},
    {"id": 2, "val": ["B"]},
    {"id": 3, "val": ["C"]},
    {"id": 4, "val": ["A", "B", "C"]},
    .
    .
    .
    {"id": 10000, "val": ["A","C"]}
]

我的目标是映射第一个列表的“ id”及其“ val”以尽可能高效地创建第二个列表。到目前为止,我的跑步时间还不是最好的:

output = []
cache = {}

for unit in my_list:
    uid = unit['id']
    value = unit['val']

    if (uid in cache):
        output[uid][value].append(value)
    else:
        cache[uid] = 1
        output.append({'id' : uid, 'values': value})

我的方法是对“ id”进行频率检查,以避免迭代2个不同的列表。我相信我的错是在理解嵌套的字典/字典列表。我觉得我可以在O(n)中得到它,如果不是更好的话,因为O(n ^ 2)超出了它的范围,很难将其增大。

请扩大我的见解,我可以使用帮助。 或任何其他方法来解决此问题。 也许map(),zip(),tuple()可能是一种更好的方法。让我知道!

编辑:我正在尝试仅使用内置函数来完成此操作。另外,最后一个字典是为了说明这一点,不仅限于我所显示的内容,还有更多的“ id”,我可以与“ val”组合使用的“ val”是A,B,C的任何ID。 / p>

更新:

这是我的最终解决方案,如果有任何改进,请告诉我!

    mapped_list = []
    cache = {}

    for item in my_list:
        id = item['id']
        val = item['val']

        if (id in cache):
            output[cache[id]]['val'].append(val)
        else:
            cache[id] = len(output)
            mapped_list.append({'id' : id, 'val': [val]})

    mapped_list.sort(key=lambda k: k['id'])
    print(output)

5 个答案:

答案 0 :(得分:0)

您可以像使用collections.defaultdict

>>> my_list
[{'id': 1, 'val': 'A'}, {'id': 4, 'val': 'A'}, {'id': 1, 'val': 'C'}, {'id': 3, 'val': 'C'}, {'id': 1, 'val': 'B'}, {'id': 2, 'val': 'B'}, {'id': 4, 'val': 'C'}, {'id': 4, 'val': 'B'}, {'id': 10000, 'val': 'A'}]
>>> from collections import defaultdict
>>> d = defaultdict(list)
>>> for item in my_list:
...   d[item['id']].append(item['val'])
... 
>>> mapped_list = [{'id': key, 'val': val} for key,val in d.items()]
>>> mapped_list = sorted(mapped_list, key=lambda x: x['id']) # just to make it always sorted by `id`
>>> import pprint
>>> pprint.pprint(mapped_list)
[{'id': 1, 'val': ['A', 'C', 'B']},
 {'id': 2, 'val': ['B']},
 {'id': 3, 'val': ['C']},
 {'id': 4, 'val': ['A', 'C', 'B']},
 {'id': 10000, 'val': ['A']}]

答案 1 :(得分:0)

如果有多个val和同一个id,则可以使用类似的设置:

my_list = [
    {"id": 1, "val": "A"},
    {"id": 4, "val": "A"},
    {"id": 1, "val": "C"},
    {"id": 3, "val": "C"},
    {"id": 1, "val": "B"},
    {"id": 2, "val": "B"},
    {"id": 4, "val": "C"},
    {"id": 4, "val": "B"},
    {"id": 10000, "val": "A"}
]

from collections import defaultdict
ddict = defaultdict(set)
for lst in my_list:
    ddict[lst['id']].add(lst['val'])

result = [{"id" : k,"val" : list(v)} for k,v in ddict.items()]
sorted(result,key = lambda x : x['id'])

[{'id': 1, 'val': ['C', 'A', 'B']},
 {'id': 2, 'val': ['B']},
 {'id': 3, 'val': ['C']},
 {'id': 4, 'val': ['C', 'A', 'B']},
 {'id': 10000, 'val': ['A']}]

dict(或defaultdict)和set中插入或搜索具有O(1)的复杂度,而排序函数具有O(NlogN),因此总体上{{1} }

答案 2 :(得分:0)

我认为您将无法比O(n*log(n))做得更好:

from collections import defaultdict

vals = defaultdict(list)
my_list.sort(key=lambda x: x['val'])

for i in my_list:
    vals[i['id']].append(i['val'])

output = [{'id': k, 'val': v} for k, v in vals.items()]
output.sort(key=lambda x: x['id'])

输出:

[{'id': 1, 'val': ['A', 'B', 'C']},
 {'id': 2, 'val': ['B']},
 {'id': 3, 'val': ['C']},
 {'id': 4, 'val': ['A', 'B', 'C']},
 {'id': 1000, 'val': ['A']}]

答案 3 :(得分:0)

my_list=[
    {"id": 1, "val": 'A'},
    {"id": 4, "val": "A"},
    {"id": 1, "val": "C"},
    {"id": 3, "val": "C"},
    {"id": 1, "val": "B"},
    {"id": 2, "val": "B"},
    {"id": 4, "val": "C"},
    {"id": 4, "val": "B"},
    {"id": 10000, "val": "A"}
]

temp_dict = {}
for item in my_list:
  n, q = item.values()
  if not n in temp_dict:
    temp_dict[n] = []
  temp_dict.get(n,[]).append(q)

mapped_list = [{'id': n, 'val': q} for n,q in temp_dict.items()]
mapped_list = sorted(mapped_list, key = lambda x : x['id'])
print(mapped_list)

答案 4 :(得分:0)

我是使用 setdefault

创建的mapd_list
d = {}
for i in my_list:
    d.setdefault(i['id'], []).append(i['val'])
mapped_list = [{'id':key, 'val': val} for key,val in sorted(d.items())]
print(mapped_list)
setdefault 相比,

defaultdict 具有更好的性能。

我只是使用另一种方法来创建map_list的答案