【问题标题】:Select element in list of values in dictionary在字典中的值列表中选择元素
【发布时间】:2019-04-04 10:38:32
【问题描述】:

我有一本字典,其中的值是包含 2 个或更多元素的列表。 我想根据列表中只有 2 个元素的其他值,对具有 2 个以上元素的值进行切片。

我知道我可以将所有值元素附加到一个列表中,然后只计算最常见的,但我需要保留有关键和字典格式的信息,所以它真的不起作用。而且我似乎无法弄清楚如何解决这个问题。

我的字典是这样的

start_dict = {
    'Key1': [243928620, 243938319],
    'Key2': [243928620, 243938319],
    'Key3': [243928620, 243931757, 243938319],
    'Key4': [243928620, 243938319, 243938323],
    'Key5': [243928634, 243938316],
    'Key6': [243928620, 243938319],
    'Key7': [243928634, 243938317],
    'Key8': [243928620, 243938329,243938387]
}

我想让所有值列表中的元素 1 保持不变,因为它是一个起始坐标,其余的是给定间隔的潜在结束坐标。

然后,对于那些在其列表中具有超过 2 个元素的值(键 3、4 和 8),我想将该元素保留在其值列表中,这在其他键的其他值列表中最常见,即key3 和 4 的情况,因为它们都包含最频繁的结束坐标 243938319。

如果它们不存在于其他任何一个中,我将保留它们,这是键 8 的情况。

所有键中出现频率最高的值是开始位置 243928620 和结束位置 243938319。所以理想的输出应该是

start_dict = {
    'Key1': [243928620, 243938319],
    'Key2': [243928620, 243938319],
    'Key3': [243928620, 243938319],
    'Key4': [243928620, 243938319],
    'Key5': [243928634, 243938316],
    'Key6': [243928620, 243938319],
    'Key7': [243928634, 243938317],
    'Key8': [243928620, 243938329,243938387]
}

我似乎无法理解如何做到这一点,如果它甚至可以以一种聪明的方式完成的话。

你们中的任何人都可以帮忙吗?感谢您的宝贵时间。

【问题讨论】:

    标签: python list dictionary


    【解决方案1】:

    这是一种方法:

    from collections import Counter
    from pprint import pprint
    
    def reduce_coords(data):
        # Counter of second list element for 2-element lists
        count = Counter(v[1] for v in data.values() if len(v) == 2)
        # Result dict
        result = {}
        # Iterate data entries
        for k, v in data.items():
            # Modify lists longer than two with at least one element in the counter
            if len(v) > 2 and any(elem in count for elem in v[1:]):
                # Replace list with first element and following element with max count
                v = [v[0], max(v[1:], key=lambda elem: count.get(elem, 0))]
            # Add to result
            result[k] = v
        return result
    
    start_dict = {
        'Key1': [243928620, 243938319],
        'Key2': [243928620, 243938319],
        'Key3': [243928620, 243931757, 243938319],
        'Key4': [243928620, 243938319, 243938323],
        'Key5': [243928634, 243938316],
        'Key6': [243928620, 243938319],
        'Key7': [243928634, 243938317],
        'Key8': [243928620, 243938329,243938387]
    }
    pprint(reduce_coords(start_dict))
    # {'Key1': [243928620, 243938319],
    #  'Key2': [243928620, 243938319],
    #  'Key3': [243928620, 243938319],
    #  'Key4': [243928620, 243938319],
    #  'Key5': [243928634, 243938316],
    #  'Key6': [243928620, 243938319],
    #  'Key7': [243928634, 243938317],
    #  'Key8': [243928620, 243938329, 243938387]}
    

    【讨论】:

    • 感谢这是一个非常好的解决方案。很好地结合了计数器和 lambda。
    【解决方案2】:

    关于存储此信息的不同结构:

    start_dict = {
        'Key1': [243928620, 243938319],
        'Key2': [243928620, 243938319],
        'Key3': [243928620, 243931757, 243938319],
        'Key4': [243928620, 243938319, 243938323],
        'Key5': [243928634, 243938316],
        'Key6': [243928620, 243938319],
        'Key7': [243928634, 243938317],
        'Key8': [243928620, 243938329,243938387]
    }
    
    modified_dict = {k:{"start":v[0], "end":v[1:]} for k, v in start_dict.items()}
    print(modified_dict)
    #Output:
    {'Key1': {'start': 243928620, 'end': [243938319]},
     'Key2': {'start': 243928620, 'end': [243938319]},
     'Key3': {'start': 243928620, 'end': [243931757, 243938319]},
     'Key4': {'start': 243928620, 'end': [243938319, 243938323]},
     'Key5': {'start': 243928634, 'end': [243938316]},
     'Key6': {'start': 243928620, 'end': [243938319]},
     'Key7': {'start': 243928634, 'end': [243938317]},
     'Key8': {'start': 243928620, 'end': [243938329, 243938387]}}
    

    像上面这样的 dicts 可能会为使用和维护提供更清晰的画面,您可以考虑使用这样的结构。或者,也许 2 长度的元组也可以工作,但我发现这个版本最易读。

    以此为起点:

    #collect all possible end points for every key, and combine in a list
    end_points = []
    for k, v in modified_dict.items():
        end_points.extend(v["end"])
    
    #find the most common end point
    from collections import Counter
    most_common = Counter(end_points).most_common(1)[0][0]
    
    #Adjust the end points if the most common end point is found
    for k, v in modified_dict.items():
        if most_common in v["end"]:
            modified_dict[k]["end"] = [most_common]
    print(modified_dict)
    #Output:
    {'Key1': {'start': 243928620, 'end': [243938319]},
     'Key2': {'start': 243928620, 'end': [243938319]},
     'Key3': {'start': 243928620, 'end': [243938319]},
     'Key4': {'start': 243928620, 'end': [243938319]},
     'Key5': {'start': 243928634, 'end': [243938316]},
     'Key6': {'start': 243928620, 'end': [243938319]},
     'Key7': {'start': 243928634, 'end': [243938317]},
     'Key8': {'start': 243928620, 'end': [243938329, 243938387]}}
    

    【讨论】:

    • 感谢您的建议。我从来没有想过拥有一个dicts of dicts,我可以看到它可以派上用场,因为我有很多不同的坐标,所以这提供了一个很好的概述!
    【解决方案3】:

    我更喜欢另一个答案,但这仍然可以教你一些关于列表理解的知识。

    #

    创建一个包含所有端点列表的 dic:

    startpoints = {k:v[0]  for k,v in start_dict.items()}
    endpoints = {k:v[1:] for k,v in start_dict.items()}
    

    然后将其展平:

    endpoints_flatten = [value for list in endpoints.values() for value in list]
    

    创建一个包含所有端点的计数器:

    from collections import Counter
    c = Counter(endpoints_flatten)
    

    创建一个为您提供列表中最常见的函数:

    def most_com(list_endpoint,c):
        return max(list_endpoint, key=lambda l : c[l])
    

    现在遍历端点列表,只保留最常见的一个:

    common_endpoint = {k:most_com(list_endpoint,c) for k,list_endpoint in endpoints.items()}
    

    现在全部输出:

    output = {k:v + common_endpoint[k] for k,v in startpoints.items()}
    

    【讨论】:

    • 如果多个值是唯一的,实际上我的不会保留它
    • 尽管它不保留多个唯一值。这仍然是展示如何结合列表理解和字典的有用方式。谢谢。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-11-24
    • 2016-01-02
    • 1970-01-01
    • 2017-04-19
    • 2021-12-12
    相关资源
    最近更新 更多