如何将相同的值分组到同一个键中?

huangapple go评论61阅读模式
英文:

How to group the same values into same key?

问题

{
    '2001': {
        'k': [
            {'num': '2001', 'e1': 'k', 'e2': 'r', 'e3': 'e'}
        ]
    },
    '2002': {
        'k': [
            {'num': '2002', 'e1': 'k', 'e2': 'r', 'e3': 'i'}
        ],
        'p': [
            {'num': '2002', 'e1': 'p', 'e2': 'r', 'e3': 'i'}
        ]
    },
    '2004': {
        'p': [
            {'num': '2004', 'e1': 'p', 'e2': 'a', 'e3': 'p'},
            {'num': '2004', 'e1': 'p', 'e2': 's', 'e3': 'f'}
        ]
    }
}
英文:

I have an assignment to do this things without import any helpful function, could you guys help me?
Thanks!

data = [
    ['num','e1','e2','e3'],
    ['2002','p','r','i'],
    ['2002','k','r','i'],
    ['2001','k','r','e'],
    ['2004','p','a','p'],
    ['2004','p','s','f']
]

newlist = [
    {'num': '2001', 'e1': 'k', 'e2': 'r', 'e3': 'e'},
    {'num': '2002', 'e1': 'p', 'e2': 'r', 'e3': 'i'},
    {'num': '2002', 'e1': 'k', 'e2': 'r', 'e3': 'i'},
    {'num': '2004', 'e1': 'p', 'e2': 'a', 'e3': 'p'},
    {'num': '2004', 'e1': 'p', 'e2': 's', 'e3': 'f'}
]

How can I convert newlist into this by num is main key and next key is e1

{
    '2001':{
        'k':[{'num': '2001', 'e1': 'k', 'e2': 'r', 'e3': 'e'}]
    },
    '2002':{
        'k':[{'num': '2002', 'e1': 'k', 'e2': 'r', 'e3': 'i'}],
        'p':[{'num': '2002', 'e1': 'p', 'e2': 'r', 'e3': 'i'}]
    },
    '2004':{
        'p':[{'num': '2004', 'e1': 'p', 'e2': 'a', 'e3': 'p'}, {'num': '2004', 'e1': 'p', 'e2': 's', 'e3': 'f'}]
    }
}

2001 and 2002 have only k and k have only one data so it will be the only one member of k
you will see its form { num: {e1: [ {'num':..., 'e1': ..., 'e2': ... }, ... ], ...}, ... }

答案1

得分: 0

一种方法是遍历输入列表(datanewlist)并使用 .setdefault.append 来填充嵌套的字典或列表。


data 中获取嵌套字典:

result, kList, vData = {}, data[0], data[1:]
for r in vData:
    k_outer, k_inner = r[:2]
    dict_inner = result.setdefault(k_outer, {})
    list_inner = dict_inner.setdefault(k_inner, [])
    list_inner.append(dict(zip(kList, r)))

newlist 中获取嵌套字典:

# newlist = [dict(zip(data[0],r)) for r in data[1:]] # <-- 从 data 获取 newlist

result, k_outer_key, k_inner_key = {}, 'num', 'e1'
for r in newlist:
    k_outer, k_inner = r.get(k_outer_key), r.get(k_inner_key)
    dict_inner = result.setdefault(k_outer, {})
    list_inner = dict_inner.setdefault(k_inner, [])
    list_inner.append(r)

你也可以使用字典推导式来创建一个包含空列表的嵌套字典,然后遍历 datanewlist 并将输入列表中的每个字典添加到嵌套字典中相应的列表中。

(在定义嵌套字典时,你可以直接使用列表推导式为每个嵌套键筛选输入列表,但在单独的循环中执行此操作实际上会减少你循环遍历输入数据的总次数。)


data 中获取嵌套字典,你可以使用:

kList, vData = data[0], data[1:]

result = {k_outer: {
    k_inner: [] for k, k_inner, *_ in vData if k==k_outer
} for k_outer in {k1 for k1, *_ in vData}}

for r in vData: result[r[0]][r[1]].append(dict(zip(kList,r)))

## 或者
''' ## [稍微不那么高效]
kList, vData = data[0], data[1:]
result = {k_outer: {
    k_inner: [dict(zip(kList,x)) for x in vData if x[0]==k_outer and x[1]==k_inner] 
    for k, k_inner, *_ in vData if k==k_outer
} for k_outer in {k1 for k1, *_ in vData}}
''' 

<br>

newlist 中获取嵌套字典,你可以使用:

k_outer, k_inner = 'num', 'e1'

result = {k: {
    d.get(k_inner): [] for d in newlist if k==d.get(k_outer)
} for k in {r.get(k_outer) for r in newlist}}

for r in newlist: result[r.get(k_outer)][r.get(k_inner)].append(r)

## 或者
''' ## [稍微不那么高效]
k_outer, k_inner = 'num', 'e1'
result = {k: {d.get(k_inner): [
    x for x in newlist if x.get(k_outer)==k and x.get(k_inner)==d.get(k_inner)
] for d in newlist if k==d.get(k_outer)} for k in {r.get(k_outer) for r in newlist}}
'''

无论采用哪种方法,result 应该看起来像:

{
  '2004': {
    'p': [{'num': '2004', 'e1': 'p', 'e2': 'a', 'e3': 'p'}, {'num': '2004', 'e1': 'p', 'e2': 's', 'e3': 'f'}]
  },
  '2002': {
    'p': [{'num': '2002', 'e1': 'p', 'e2': 'r', 'e3': 'i'}],
    'k': [{'num': '2002', 'e1': 'k', 'e2': 'r', 'e3': 'i'}]
  },
  '2001': {
    'k': [{'num': '2001', 'e1': 'k', 'e2': 'r', 'e3': 'e'}]
  }
}
英文:

One way would be to loop through the input list (data or newlist) and use .setdefault and .append to fill up the nested dictionary or lists.


To get the nested dictionary from data:

result, kList, vData = {}, data[0], data[1:]
for r in vData:
    k_outer, k_inner = r[:2]
    dict_inner = result.setdefault(k_outer, {})
    list_inner = dict_inner.setdefault(k_inner, [])
    list_inner.append(dict(zip(kList, r)))

To get the nested dictionary from newlist:

# newlist = [dict(zip(data[0],r)) for r in data[1:]] # &lt;-- get newlist from data

result, k_outer_key, k_inner_key = {}, &#39;num&#39;, &#39;e1&#39;
for r in newlist:
    k_outer, k_inner = r.get(k_outer_key), r.get(k_inner_key)
    dict_inner = result.setdefault(k_outer, {})
    list_inner = dict_inner.setdefault(k_inner, [])
    list_inner.append(r)

You can also use dictionary comprehension to create a nested dictionary containing empty lists and then loop through data or newlist and add each dictionary in the input list to whichever list it belongs to in the nested dictionary.

(You could filter the input list for each nested key right away with list comprehension when you're defining the nested dictionary, but doing it in a separate loop actually reduces the total number of times you loop through the input data.)


To get the nested dictionary from data, you can use

kList, vData = data[0], data[1:]

result = {k_outer: {
    k_inner: [] for k, k_inner, *_ in vData if k==k_outer
} for k_outer in {k1 for k1, *_ in vData}}

for r in vData: result[r[0]][r[1]].append(dict(zip(kList,r)))

## OR 
&#39;&#39;&#39; ## [SLIGHTLY LESS EFFICIENT]
kList, vData = data[0], data[1:]
result = {k_outer: {
    k_inner: [dict(zip(kList,x)) for x in vData if x[0]==k_outer and x[1]==k_inner] 
    for k, k_inner, *_ in vData if k==k_outer
} for k_outer in {k1 for k1, *_ in vData}}
&#39;&#39;&#39; 

<br>

To get the nested dictionary from newlist, you can use

k_outer, k_inner = &#39;num&#39;, &#39;e1&#39;

result = {k: {
    d.get(k_inner): [] for d in newlist if k==d.get(k_outer)
} for k in {r.get(k_outer) for r in newlist}}

for r in newlist: result[r.get(k_outer)][r.get(k_inner)].append(r)

## OR 
&#39;&#39;&#39; ## [SLIGHTLY LESS EFFICIENT]
k_outer, k_inner = &#39;num&#39;, &#39;e1&#39;
result = {k: {d.get(k_inner): [
    x for x in newlist if x.get(k_outer)==k and x.get(k_inner)==d.get(k_inner)
] for d in newlist if k==d.get(k_outer)} for k in {r.get(k_outer) for r in newlist}}
&#39;&#39;&#39;

Whichever approach is taken, result should look like

> py
&gt; {
&gt; &#39;2004&#39;: {
&gt; &#39;p&#39;: [{&#39;num&#39;: &#39;2004&#39;, &#39;e1&#39;: &#39;p&#39;, &#39;e2&#39;: &#39;a&#39;, &#39;e3&#39;: &#39;p&#39;}, {&#39;num&#39;: &#39;2004&#39;, &#39;e1&#39;: &#39;p&#39;, &#39;e2&#39;: &#39;s&#39;, &#39;e3&#39;: &#39;f&#39;}]
&gt; },
&gt; &#39;2002&#39;: {
&gt; &#39;p&#39;: [{&#39;num&#39;: &#39;2002&#39;, &#39;e1&#39;: &#39;p&#39;, &#39;e2&#39;: &#39;r&#39;, &#39;e3&#39;: &#39;i&#39;}],
&gt; &#39;k&#39;: [{&#39;num&#39;: &#39;2002&#39;, &#39;e1&#39;: &#39;k&#39;, &#39;e2&#39;: &#39;r&#39;, &#39;e3&#39;: &#39;i&#39;}]
&gt; },
&gt; &#39;2001&#39;: {
&gt; &#39;k&#39;: [{&#39;num&#39;: &#39;2001&#39;, &#39;e1&#39;: &#39;k&#39;, &#39;e2&#39;: &#39;r&#39;, &#39;e3&#39;: &#39;e&#39;}]
&gt; }
&gt; }
&gt;

huangapple
  • 本文由 发表于 2023年4月4日 16:29:29
  • 转载请务必保留本文链接:https://go.coder-hub.com/75927144.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定