Python中匹配长度不相等的列表到列

4

您能否将长度不等的列表列表写入一系列列中,同时匹配另一个列表的顺序?

order = ['bx', 'cs', 'lb', 'pc']

totals = [
    [{'unit': 'pc', 'sum': Decimal('3.00')}],
    [{'unit': 'bx', 'sum': Decimal('3.00')}, {'unit': 'pc', 'sum': Decimal('16.00')}],
    [{'unit': 'bx', 'sum': Decimal('6.00')}, {'unit': 'lb', 'sum': Decimal('24.00')}, {'unit': 'pc', 'sum': Decimal('63.00')}],
    [{'unit': 'pc', 'sum': Decimal('36.00')}],
    [{'unit': 'bx', 'sum': Decimal('31.00')}]
]

desired_format = [
    ['', '', '', '3.00 pc'],
    ['3.00 bx', '', '', '16.00 pc'],
    ['6.00 bx', '', '24.00 lb', '63:00 pc'],
    ['', '', '', '36:00 pc'],
    ['31.00 bx', '', '', ''],
]

我尝试了下面的代码,但如果按顺序没有出现所有四个单元,则无法达到预期的效果。
desired_format = [[]]
for total in totals:
    data = []
    for idx, um in enumerate(total):
        if um['unit'] == order[idx]:
            data.append(str(um['sum'] + ' ' + str(um['unit'])))
        else:
            data.append('')
    desired_format.append(data)

我也尝试过这个方法,但最终出现了太多的空列和列顺序不均/无序的情况。
desired_format = [[]]
for total in totals:
    data = []
    for um in total:
        for unit in order:
            if um['unit'] == unit:
                data.append(str(um['sum'] + ' ' + str(um['unit'])))
            else:
                data.append('')
    desired_format.append(data)

1
在你的第一个输出中,你是想要['3.00 bx', '', '', ''],就像你所说的那样,还是想要['', '', '', '3.00 pc'] - Jon
@Jon 谢谢,我已经更正了。 - bdoubleu
5个回答

0

这不会是最有效的方法

converters = [{dict['unit']: dict['sum'] for dict in total} for total in totals]
desired_format = [[str(converter[item])+' '+item if item in converter else '' for item in order] for converter in converters]

这个想法是你的totals是一个字典列表的列表。使用列表推导式,Converters将其转换为一个字典列表。

然后,您可以在其中一个字典上进行列表推导,以通过它迭代顺序:如果订单中的项目存在,则给出所需的输出,否则给出''。

可能有一种方法可以在不首先生成转换器的情况下完成此操作,这可能会使代码更快。


0
我建议您使用以下代码,基于您的原始帖子:
desired_format = []
for total in totals:
    data = []
    for orderValue in order:
        found = False
        for um in total:
            if um['unit'] == orderValue:
                found = True
                break
        if found:
            data.append(str(um['sum'] + ' ' + str(um['unit'])))
        else:
            data.append('')
    desired_format.append(data)

print(desired_format)

0

你的尝试还算不错,但是存在一些问题(忽略了一些括号没有闭合)。

首先,你把初始化列表写成了 desiredFormat = [[]],这样会创建一个列表,并将第一个元素设为空列表。相反,你只需要创建一个空列表[],然后将后续的列表添加到其中。

此外,在循环列表时,你为每个部分都创建了新的列表元素,而不是在存在第二个对象时进行覆盖。

试试这个:

desired_format = []
for total in totals:
    data = [''] * len(order)
    for um in total:
        for i, unit in enumerate(order):
            if um['unit'] == unit:
                data[i] = str(um['sum']) + ' ' + str(um['unit'])
    desired_format.append(data)

首先创建一个空列表,然后随着循环的进行,将额外的信息添加到列表中。


0
这里有一个使用 collections.defaultdict 的解决方案:
from collections import defaultdict

d = defaultdict(list)

for idx, i in enumerate(totals):
    for j in order:
        d_item = next((str(k['sum']) + ' ' + j for k in i if k['unit'] == j), '')
        d[idx].append(d_item)

res = [d[i] for i in range(len(totals))]

# [['', '', '', '3.00 pc'],
#  ['3.00 bx', '', '', '16.00 pc'],
#  ['6.00 bx', '', '24.00 lb', '63.00 pc'],
#  ['', '', '', '36.00 pc'],
#  ['31.00 bx', '', '', '']]

0
以下解决方案依赖于创建一个维度为 len(order) x len(totals) 的表格,最初填充默认值为 ''。然后,我们根据 totals 中已知的值填充表格,其余部分留空为 ''
# Have your order as dict for quick lookup
order_keys = dict(map(reversed, enumerate(order)))
# This output the indexing: {'bx': 0, 'cs': 1, 'lb': 2, 'pc': 3}

# Create the empty table for the desired output, default value will be ''
output = [[''] * len(order_keys) for _ in range(len(totals))]
# output:
# [['', '', '', ''],
#  ['', '', '', ''],
#  ['', '', '', ''],
#  ['', '', '', ''],
#  ['', '', '', '']]

for index, row in enumerate(totals):
    for col in row:
        unit = col['unit']
        output[index][order_keys[unit]] = '{} {}'.format(col['sum'], col['unit'])

# output:
# [['', '', '', '3.00 pc'],
#  ['3.00 bx', '', '', '16.00 pc'],
#  ['6.00 bx', '', '24.00 lb', '63.00 pc'],
#  ['', '', '', '36.00 pc'],
#  ['31.00 bx', '', '', '']]

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