【问题标题】:Group the elements in a list of lists into a nested dictionary将列表列表中的元素分组到嵌套字典中
【发布时间】:2019-07-03 15:58:20
【问题描述】:

我有以下列表示例列表(仅显示一个部分):

[
["4YBB|1|AA|A|262", "4YBB|1|AA|A|263", "s35"], 
["4YBB|1|AA|U|261", "4YBB|1|AA|A|263", "tSH",], 
["4YBB|1|AA|U|261", "4YBB|1|AA|C|264", "ntSH", "s55"], 
["4YBB|1|AA|G|259", "4YBB|1|AA|C|267", "cWW"], 
["4WOI|1|DA|A|262", "4WOI|1|DA|A|263", "s35", "cWW"], 
["4WOI|1|DA|C|264", "4WOI|1|DA|G|265", "s35"]
....
]

我想根据以下键列表将此列表中的元素分组到嵌套字典中:

outer_key = ["4YBB|1|AA", "4WOI|1|DA"]
inner_key = [(259, 267), (259, 260), (260, 261), (260, 265), (260, 267), (261, 263), (261, 264), (262, 263), (264, 265), (265, 267)]

如您所见,外部键表示内部列表的索引 [0] 和索引 [1] 处元素的子集,而内部键元组值表示索引 [0] 和索引 [ 1] 使用 '|' 分割时的内部列表特点。内部键元组表示可能具有“交互”的位置 (x,y) 的所有可能组合(内部列表的索引 [2] 向前)。因此,并非所有键都有与之关联的值。如果不存在特定的内部元组键,则将“-”附加到其值。

pw_info = {
 "4YBB|1|AA" : {

            (259, 267): "cWW",
            (259, 260): "-",
            (260, 261): "-",
            (260, 265): "-",
            (260, 267): "-",
            (261, 263): "tSH",
            (261, 264): "ntSH;s55",
            (262, 263): "s35",
            (264, 265): "-",
            (265, 267): "s35"

           },

 "4WOI|1|DA" : {

            (259, 267): "-",
            (259, 260): "-",
            (260, 261): "-",
            (260, 265): "-",
            (260, 267): "-",
            (261, 263): "-",
            (261, 264): "-",
            (262, 263): "s35;cWW",
            (264, 265): "s35",
            (265, 267): "-"

            }            
}

必须根据外部和内部键列表对键进行排序。此外,内部列表可能有超过 3 个元素。如果有超过 3 个元素,则使用“;”将索引 [2] 和更高处的元素连接在一起作为内部字典值(例如: (261, 264): "ntSH;s55" )。最好的方法是什么?

【问题讨论】:

  • 一些空的项目,即 (260, 261): "-" 是从哪里来的?我在初始列表中没有看到这些?
  • @dasvootz 一些内部列表具有这些元组值的组合。为了简单起见,我没有展示所有内容。

标签: python list dictionary


【解决方案1】:

至于“键必须根据外部和内部键列表进行排序” - 请记住,字典是无序的数据结构。
OrderedDict 对象是另一种选择。

from collections import OrderedDict
import pprint

input_list = [
    ["4YBB|1|AA|A|262", "4YBB|1|AA|A|263", "s35"],
    ["4YBB|1|AA|U|261", "4YBB|1|AA|A|263", "tSH", ],
    ["4YBB|1|AA|U|261", "4YBB|1|AA|C|264", "ntSH", "s55"],
    ["4YBB|1|AA|G|259", "4YBB|1|AA|C|267", "cWW"],
    ["4WOI|1|DA|A|262", "4WOI|1|DA|A|263", "s35", "cWW"],
    ["4WOI|1|DA|C|264", "4WOI|1|DA|G|265", "s35"]
]

outer_keys = ["4YBB|1|AA", "4WOI|1|DA"]
inner_keys = [(259, 267), (259, 260), (260, 261), (260, 265), (260, 267),
             (261, 263), (261, 264), (262, 263), (264, 265), (265, 267)]

# prepopulated dict indexed by `outer_keys` and 
# containing OrderedDicts with default values for `inner_keys`  
pw_info = {k: OrderedDict({t: '-' for t in inner_keys}) for k in outer_keys}

for sub_lst in input_list:
    # extract starting slice from first 2 items (like `4YBB|1|AA`)
    k0, k1 = sub_lst[0][:9], sub_lst[1][:9]
    # check if 2 slices are equal and contained in `pw_info` dict (i.e. `outer_keys`)
    if k0 == k1 and k0 in pw_info:
        v1, v2 = sub_lst[0], sub_lst[1]
        # `sub_key` is aimed to be a key for inner dict of the predefined `pw_info` dict
        # thus it's composed as a tuple of trailing numbers of the first 2 items
        # in sub_list (ex. `(262, 263)`)
        sub_key = (int(v1[v1.rfind('|')+1:]), int(v2[v2.rfind('|')+1:]))
        pw_info[k0][sub_key] = sub_lst[2] if len(sub_lst) == 3 else ';'.join(sub_lst[2:])

pprint.pprint(pw_info)

输出:

{'4WOI|1|DA': OrderedDict([((259, 267), '-'),
                           ((259, 260), '-'),
                           ((260, 261), '-'),
                           ((260, 265), '-'),
                           ((260, 267), '-'),
                           ((261, 263), '-'),
                           ((261, 264), '-'),
                           ((262, 263), 's35;cWW'),
                           ((264, 265), 's35'),
                           ((265, 267), '-')]),
 '4YBB|1|AA': OrderedDict([((259, 267), 'cWW'),
                           ((259, 260), '-'),
                           ((260, 261), '-'),
                           ((260, 265), '-'),
                           ((260, 267), '-'),
                           ((261, 263), 'tSH'),
                           ((261, 264), 'ntSH;s55'),
                           ((262, 263), 's35'),
                           ((264, 265), '-'),
                           ((265, 267), '-')])}

【讨论】:

  • 这太完美了!在我接受这个答案之前,您介意解释一下关于 sub_key 部分的逻辑吗?谢谢
  • @TheEmperor,欢迎,我已经通过cmets添加了解释
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-12-12
  • 2023-04-10
  • 2017-12-27
  • 2017-06-17
  • 1970-01-01
  • 2012-09-06
相关资源
最近更新 更多