【问题标题】:Convert Dash Seperated String Data to Nested Dictionary/List in Python将破折号分隔的字符串数据转换为 Python 中的嵌套字典/列表
【发布时间】:2019-05-29 16:01:06
【问题描述】:

我有一个字符串列表,其中列表中的每个元素都采用指定格式 a-b-c,其中每个 a、b、c 都是整数,例如,包含大约 8000 个长度为 n-m-k 的元素。

myList = ['1-1-1', '1-1-2', '1-2-1', '1-2-2', '1-3-1', ...., n-m-k]

我正在尝试找到一种简单有效的方法将其转换为

myDict = {
'1': {
    '1-1': ['1-1-1','1-1-2','1-1-3','1-1-4'],
    '1-2': ['1-2-1','1-2-2'],
    '1-3': ['1-3-1']
},
....,
'n': {.....,'n-m':[....,'n-m-k']}
}

因为我需要基于这些元素运行操作,例如就地链表。

实现这一目标的最简单方法是什么?

提前致谢,

【问题讨论】:

  • 没有简单的方法。您必须拆分列表中的每个元素并循环遍历 n、m 和 k 并将其保存到您的字典中。你的逻辑也不是特别清楚。你能举例说明1-1-1 会产生什么吗? 1-2-11-1-2 也是如此

标签: python list dictionary linked-list nested


【解决方案1】:

如果可以接受整数元组,则可以使用:

x = ['1-1-1','1-1-2', '1-2-1', '1-2-2', '1-3-1']
y3 = [tuple(map(int,a.split('-'))) for a in x]
y2 = set(a[:2] for a in y3)
y1 = set(a[0] for a in y2)

d = {}
for k1 in y1:
    d1 = {}
    d[k1] = d1
    for k2 in (z for z in y2 if z[0]==k1):
        a2 = []
        d1[k2] = a2
        for a in (z for z in y3 if z[0]==k1 and z[1]==k2[1]):
            a2.append(a)

但如果你真的需要字符串,你可以简单地通过以下方式连接键:

x = ['1-1-1','1-1-2', '1-2-1', '1-2-2', '1-3-1']
y3 = [tuple(a.split('-')) for a in x]
y2 = set(a[:2] for a in y3)
y1 = set(a[0] for a in y2)


d = {}
for k1 in y1:
    d1 = {}
    d[k1] = d1
    for k2 in (z for z in y2 if z[0]==k1):
        a2 = []
        d1['-'.join(k2)] = a2
        for a in (z for z in y3 if z[0]==k1 and z[1]==k2[1]):
            a2.append('-'.join(a))

d
# returns:
{'1': {'1-1': ['1-1-1', '1-1-2'], '1-2': ['1-2-1', '1-2-2'], '1-3': ['1-3-1']}}

【讨论】:

    【解决方案2】:

    IIUC,你想要的输出实际上是这样的:

    myDict = {
        '1': {
            '1-1': ['1-1-1','1-1-2','1-1-3','1-1-4'],
            '1-2': ['1-2-1','1-2-2'],
            '1-3': ['1-3-1']
        },
        ....,
        'n': {.....,'n-m':[....,'n-m-k']}
    }`
    

    这是使用itertools.groupby的一种方法:

    from itertools import groupby
    myList = [
        '1-1-1','1-1-2','1-2-1','1-2-2','1-3-1', '2-1-1', '2-2-2', '2-2-3', '4-5-6'
    ]
    
    # a helper function
    def mySplit(s, max_split):
        return {
            v: list(g) 
            for v, g in groupby(
                s, 
                lambda x: "-".join(x.split("-", max_split)[:max_split])
            )
        }
    
    myDict = {v: mySplit(g, 2) for v, g in groupby(myList, lambda x: x.split("-", 1)[0])}
    
    print(myDict)
    #{'1': {'1-1': ['1-1-1', '1-1-2'], '1-2': ['1-2-1', '1-2-2'], '1-3': ['1-3-1']},
    # '2': {'2-1': ['2-1-1'], '2-2': ['2-2-2', '2-2-3']},
    # '4': {'4-5': ['4-5-6']}}
    

    通过一些工作,这可以推广到任意数量的破折号。

    【讨论】:

    • 这里需要注意的是,这是假设原始列表已排序。
    【解决方案3】:

    您可以使用列表推导:

    myList = ['1-1-1', '1-1-2', '1-2-1', '1-2-2', '1-3-1']
    _split = list(map(lambda x:x.split('-'), myList))
    s, s2 = {a for a, *_ in _split}, {f'{a}-{b}' for a, b, _ in _split}
    new_data = {i:{c:[h for h in myList if h.startswith(c)] for c in s2 if c[0] == i} for i in s}
    

    输出:

    {'1': {'1-2': ['1-2-1', '1-2-2'], '1-1': ['1-1-1', '1-1-2'], '1-3': ['1-3-1']}
    

    【讨论】:

      猜你喜欢
      • 2013-05-08
      • 1970-01-01
      • 2020-12-16
      • 2015-07-12
      • 2012-05-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多