拆分列表字符串并创建字典。

3

我有这个列表:

lst= ['1 5','1 12','1 55','2 95', '2 66', '3 45',...]

您可以看到,每个项目都由2个数字组成,第二个数字最多为4个字符,并且它们用空格分隔。

我想将其转换为以下类似于字典的格式

dct={1:{'doc0005','doc0012','doc0055'},2:{'doc0095','doc0066'},3:{'doc0045'},...}

每个值项应为7个字符长:'doc'+someZeros+'second number'来自列表项,其中someZeros是额外的0字符,以使值为7个字符长。第一个数字将是字典的键。
我试图拆分列表的每个项目,并通过循环将其添加到字典中,但我感到困惑。

1
这里有很多精彩的解决方案。我认为我还有很长的路要学习它们。谢谢大家。 - Eric Klaus
5个回答

4
这很容易通过一个(默认)集合字典来实现。
from collections import defaultdict

d = defaultdict(set)
for l in lst:
     k, v = l.split()
     d[k].add(f'doc{int(v):04d}')  # "doc{:04d}".format(int(v))

print(d)
defaultdict(set,
            {'1': {'doc0005', 'doc0012', 'doc0055'},
             '2': {'doc0066', 'doc0095'},
             '3': {'doc0045'}})

如果您更喜欢简单词典,请将上面的结果转换为dict,或者使用稍微不那么高效的解决方案,使用dict.setdefault

d = {}
for l in lst:
    k, v = l.split()
    d.setdefault(k, set()).add(f'doc{int(v):04d}')  # "doc{:04d}".format(int(v))

print(d)
{'1': {'doc0005', 'doc0012', 'doc0055'},
 '2': {'doc0066', 'doc0095'},
 '3': {'doc0045'}}

然后对于一个字典,使用print(dict(d)) - U13-Forward
如果版本小于 Python 3.6,则将 f-strings 替换为其他内容。 - U13-Forward
1
@U9-Forward,或者升级到3.6+ :)。另外,defaultdict确实是一个dict - jpp
如果你不想使用f-strings,你可以将d[k].add(f'doc{int(v):04d}')替换为d[k].add('doc{:04d}'.format(int(v)))。但我个人认为f-strings更符合Pythonic的风格。 - Joe Patten

1
这将是一种不使用import语句的解决方案:

lst= ['1 5','1 12','1 55','2 95', '2 66', '3 45']

result = {}

for i in lst:
    k, v = i.split()
    k = int(k)
    v = 'doc{}'.format(v.zfill(4))
    if k in result:
        result[k].add(v)
    else:
        result[k] = {v}

print(result)
#{1: {'doc0005', 'doc0012', 'doc0055'}, 2: {'doc0095', 'doc0066'}, 3: {'doc0045'}}

1
或者简单使用 setdefault:
d={}
for i in l:
    d.setdefault(i.split()[0],set()).add('doc%04d' % int(i.split()[1]))
print(d)

1
如果您的列表按每个字符串的关键部分排序,您可以使用O(n)复杂度的groupby
from itertools import groupby
from operator import itemgetter

lst = ['1 5','1 12','1 55','2 95', '2 66', '3 45']
split = [list(map(int, item.split())) for item in lst]
grouper = groupby(split, key=itemgetter(0))

res = {i: {f'doc{x[1]:04d}' for x in j} for i, j in grouper}

# {1: {'doc0005', 'doc0012', 'doc0055'},
#  2: {'doc0066', 'doc0095'},
#  3: {'doc0045'}}

如果您的输入未排序,则需要先进行排序,这将是昂贵的。在这种情况下,您可以考虑使用collections.defaultdictset,具体请参见this solution

1
我个人喜欢使用groupby,因为这是一种SQL习语,当我考虑如何解决问题时,我喜欢使用它...但有时候人们更喜欢简单的东西。;-) - cs95

0

只需一个循环

d = {}
for i in lst:
    if i.split()[0] not in d:
        d[i.split()[0]] = 'doc{}'.format((i.split()[1]).zfill(4))    
    elif i.split()[0] in d:
        d[i.split()[0]] += ', doc{}'.format(i.split()[1].zfill(4))
{'1': 'doc0005, doc0012, doc0055', '2': 'doc0095, doc0066', '3': 'doc0045'}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接