合并并展平两个字典列表,使用键作为新字段。

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

Merging and flattening two lists of dictionaries using keys as new fields

问题

以下是翻译好的部分:

我有两个具有相同结构的字典列表希望将它们展开成一个单一的字典以列表2的值作为新平面字典的键

以下代码有效但感觉像是在拼凑代码可能可以通过一两个简单的综合来完成是否有比这更好的方法

它产生了以下结果

{
    'SourceIP': 'src2',
    'DestinationIP': 'dst',
    'Direction': 'dir',
    'NEW': 'newvalue'
}

以下是代码

import operator

default = [
    {"RealField": "SourceIP", "SuppliedField": "src"},
    {"RealField": "DestinationIP", "SuppliedField": "dst"},
    {"RealField": "Direction", "SuppliedField": "dir"}
]

product_mapping = [
    {"RealField": "SourceIP", "SuppliedField": "src2"},
    {"RealField": "DestinationIP", "SuppliedField": "dst2"},
    {"RealField": "NEW", "SuppliedField": "newvalue"},
]

def dictionary_from_mappings(default_mapping, product_mapping):
    default = [{i["RealField"]: i["SuppliedField"]} for i in default_mapping]
    default_flat = reduce(operator.ior, default, {})

    product = [{i["RealField"]: i["SuppliedField"]} for i in product_mapping]
    product_flat = reduce(operator.ior, product, {})
    return default_flat | product_flat

mappings = dictionary_from_mappings(default, product_mapping)
print(mappings)
英文:

I have two lists of dictionaries, each with the same structure. I wish to flatten into a single dictionary taking precedence of list 2, taking the value as the key of a new flat dictionary.

The following code works, but it feels like it's hacking together code that can probably be done via one or two simple comprehensions. Is there a better way than this?

It produces this:

{'SourceIP': 'src2', 
 'DestinationIP': 'dst', 
 'Direction': 'dir', 
 'NEW': 'newvalue'
}

Here is the code:

import operator

default = [
    {"RealField": "SourceIP",   "SuppliedField": "src"},
    {"RealField": "DestinationIP", "SuppliedField": "dst"},
    {"RealField": "Direction", "SuppliedField": "dir"}
]

product_mapping = [
    {"RealField": "SourceIP",   "SuppliedField": "src2"},
    {"RealField": "DestinationIP",   "SuppliedField": "dst2"},
    {"RealField": "NEW",   "SuppliedField": "newvalue"},
]


def dictionary_from_mappings(default_mapping, product_mapping):
    default = [{i["RealField"]:i["SuppliedField"]} for i in default_mapping]
    default_flat = reduce(operator.ior, default, {})
    
    product = [{i["RealField"]:i["SuppliedField"]} for i in product_mapping]
    product_flat = reduce(operator.ior, product, {})
    return default_flat | product_flat

mappings = dictionary_from_mappings(default, product_mapping)
print(mappings)

答案1

得分: 2

你可以使用字典解析来直接创建这些平面,就像这样:

def dictionary_from_mappings(default_mapping, product_mapping):
    default_flat = {i["RealField"]: i["SuppliedField"] for i in default_mapping}
    product_flat = {i["RealField"]: i["SuppliedField"] for i in product_mapping}
    return default_flat | product_flat
英文:

You can use dict comprehensions to create the flats directly, like this:

def dictionary_from_mappings(default_mapping, product_mapping):  
    default_flat = {i["RealField"]: i["SuppliedField"] for i in default_mapping}  
    product_flat = {i["RealField"]: i["SuppliedField"] for i in product_mapping}
    return default_flat | product_flat  

答案2

得分: 1

你的示例不是完全可重现的,但我认为这是你想要的:

def flat_dict(nested):
    return {x["RealField"]: x["SuppliedField"] for x in nested}

def dictionary_from_mappings(default_mapping, product_mapping):
    return flat_dict(default_mapping) | flat_dict(product_mapping)

关键是使用第二个函数,其中包含一个简单的字典推导,并调用它两次以消除代码重复。

英文:

Your example isn't fully reproducable, but I think this is what you want:

def flat_dict(nested):
    return {x["RealField"]: x["SuppliedField"] for x in nested}

def dictionary_from_mappings(default_mapping, product_mapping):
    return flat_dict(default_mapping) | flat_dict(product_mapping)

The key is to use a second function with a simple dict comprehension and call it twice to eliminate code duplication

答案3

得分: 0

以下是翻译好的内容:

"Comin' in hot years later as we were looking for example questions to answer and stumbled across this one."
-> "几年后,当我们正在寻找示例问题以回答时,我们偶然发现了这个问题。"

"Clearly you have the needed solutions above, but I thought i'd include the work we did for our local example here as a reference or in the event that someone find it helpful."
-> "显然,您在上面已经有所需的解决方案,但我想在这里包括我们为本地示例所做的工作,作为参考或以防有人觉得有帮助。"

"Few things I did notice / made assumptions on:"
-> "我注意到的几件事/基于的假设:"

"> wish to flatten into a single dictionary taking precedence of list 2, taking the value as the key of a new flat dictionary."
-> "> 希望将其压缩成一个单一的字典,以第2个列表为优先,并将值作为新平坦字典的键。"

"I took this to mean: for N-number of lists, when combining the dictionaries contained within them, the last list to be iterated over which contains a key:value that appears in a prior list, override to the newest value. This gets a little confusing given the example output you provided here:"
-> "我理解这意味着:对于N个列表,在合并其中包含的字典时,应迭代的最后一个列表,其中包含在先前列表中出现的“键:值”,将其覆盖为最新的值。鉴于您提供的示例输出,这有点令人困惑:"

"my assumption is it was meant to be:"
-> "我假设应该是这样的:"

"So with that assumption, we wanted to make our answer:"
-> "因此,基于这个假设,我们希望制定我们的答案:"

"1) not locked into to any hardcoded variables"
-> "1) 不锁定到任何硬编码的变量"

"2) allow to pass in N dictionaries, rather than static number of 2"
-> "2) 允许传递N个字典,而不是固定的2个"

"What we came up with:"
-> "我们想出了以下解决方案:"

"kapow kinda un-nest a list of dicts and create new k:v from values"
-> "kapow函数有点解嵌套字典列表并从值创建新的键值对"

"Function to essentially do nothing more than generate a new dictionary by iterating over a list of dictionaries, whereby the key will be the value of the first item, and the value will be the..well..value from the second item. In essence doing away with the key of the second altogether:"
-> "这个函数基本上不做任何事情,只是通过迭代字典列表生成一个新的字典,其中键将是第一个项的值,而值将是第二个项的值。本质上完全取消第二个键:"

"IE:"
-> "例如:"

"return(dict(map(lambda i: i.values(), l)))"
-> "返回(字典(map(lambda i:i.values(),l)))"

"dict_from_mappings for any number of lists of dicts combine into one"
-> "dict_from_mappings用于合并任意数量的字典列表为一个"

"L = [kapow(i) for i in args]"
-> "L = [kapow(i) for i in args]"

"return(dict(j for i in L for j in i.items()))"
-> "return(字典(j for i in L for j in i.items()))"

"Resulting in"
-> "导致"

英文:

Comin' in hot years later as we were looking for example questions to answer and stumbled across this one.

Clearly you have the needed solutions above, but I thought i'd include the work we did for our local example here as a reference or in the event that someone find it helpful.

Few things I did notice / made assumptions on:

> wish to flatten into a single dictionary taking precedence of list 2, taking the value as the key of a new flat dictionary.

I took this to mean: for N-number of lists, when combining the dictionaries contained within them, the last list to be iterated over which contains a key:value that appears in a prior list, override to the newest value. This gets a little confusing given the example output you provided here:

{
 'SourceIP': 'src2', # <-- comes from product_mapping ie: second dict
 'DestinationIP': 'dst', # <-- comes from default
 'Direction': 'dir', # <-- comes from/only appears in default
 'NEW': 'newvalue' # <-- only appears in product_mapping
}

my assumption is it was meant to be:

{
 'SourceIP': 'src2', # <-- comes from product_mapping ie: second dict
 'DestinationIP': 'dst2', # <-- comes from product_mapping ie: second dict
 'Direction': 'dir', # <-- comes from/only appears in default
 'NEW': 'newvalue' # <-- only appears in product_mapping
}

So with that assumption, we wanted to make our answer:

  1. not locked into to any hardcoded variables
  2. allow to pass in N dictionaries, rather than static number of 2

What we came up with:


def kapow(l):
    """kapow kinda un-nest a list of dicts and create new k:v from values

    Function to essentially do nothing more than generate a new dictionary by iterating over a list of dictionaries,
    whereby the key will be the value of the first item, and the value will be the..well..value from the second item.
    In essence doing away with the key of the second altogether:
    {
       "one" : 1,
       "two" : 2
    } --> {"one" : 2}

    IE: 
                    KEY -----------------------  VALUE
                     |                              |
    {"RealField": "SourceIP",   "SuppliedField": "src"}
    # kinda weird but i get it given the probable use case scenario of the source data

    Parameters
    ----------
    l : list
        Expects a list of dictionaries. 

    Examples
    --------
    >>> _l1 = [
        {"RealField": "SourceIP",   "SuppliedField": "src"},
        {"RealField": "DestinationIP", "SuppliedField": "dst"}
    ]
    >>> kapow(_l1)

    out [1]:  {'SourceIP': 'src', 'DestinationIP': 'dst'}

    """
    return(dict(map(lambda i: i.values(), l)))

def dict_from_mappings(*args):
    """dict_from_mappings for any number of lists of dicts combine into one


    Examples
    --------
    >>> default = [
        {"RealField": "SourceIP",   "SuppliedField": "src"},
        {"RealField": "DestinationIP", "SuppliedField": "dst"},
        {"RealField": "Direction", "SuppliedField": "dir"}
    ]

    >>> product_mapping = [
        {"RealField": "SourceIP",   "SuppliedField": "src2"},
        {"RealField": "DestinationIP",   "SuppliedField": "dst2"},
        {"RealField": "NEW",   "SuppliedField": "newvalue"},
    ]

    >>> a_random_af_third = [
        {"RealField": "SourceIP",   "SuppliedField": "src2"},
        {"RealField": "DestinationIP",   "SuppliedField": "dst2"},
        {"RealField": "NEW",   "SuppliedField": "newvalue"},
        {"RealField": "idk_man", "SuppliedField": "seems like a real specific issue here but yolo"}
    ]

    >>> dict_from_mappings(default, product_mapping, a_random_af_third)
    """
    
    L = [kapow(i) for i in args]

    return(dict(j for i in L for j in i.items()))


Resulting in

dict_from_mappings(default, product_mapping, a_random_af_third)

{'SourceIP': 'src2',
 'DestinationIP': 'dst2',
 'Direction': 'dir',
 'NEW': 'newvalue',
 'idk_man': 'seems like a real specific issue here but yolo'}

答案4

得分: 0

这是与前两个解决方案类似的方法,但您可以使用两个循环来遍历列表字典中的每个元素并更新新字典,然后返回它。

def dictionary_from_mappings(default, product_mapping):
    d = {}
    for i in default:
        d.update({i["RealField"]: i["SuppliedField"]})

    p = {}
    for i in product_mapping:
        p.update({i["RealField"]: i["SuppliedField"]})

    return d | p

结果是:

{
    'SourceIP': 'src2',
    'DestinationIP': 'dst2',
    'Direction': 'dir',
    'NEW': 'newvalue'
}
英文:

This is a similiar approach to the first two solutions, but you can use two loops to loop through each element in the list dictionary and update the new dictionary then return it.

def dictionary_from_mappings(default, product_mapping):
d = {}
for i in default:
d.update({i["RealField"]: i["SuppliedField"]})
p = {}
for i in product_mapping:
p.update({i["RealField"]: i["SuppliedField"]})
return d | p

The result is:

 {'SourceIP': 'src2', 
'DestinationIP': 'dst2', 
'Direction': 'dir', 
'NEW': 'newvalue'}

huangapple
  • 本文由 发表于 2023年6月22日 17:01:30
  • 转载请务必保留本文链接:https://go.coder-hub.com/76530205.html
匿名

发表评论

匿名网友

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

确定