Python匹配列表的长度与列不相等

时间:2018-03-15 12:28:39

标签: python python-3.x

您是否可以列出不等长度的列表并将其写入一系列列,同时匹配另一个列表的顺序?

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', '', '', ''],
]

我已尝试过以下但如果按顺序排列所有4个单位,则无法正常工作。

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)

5 个答案:

答案 0 :(得分: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]

这个想法是你的总数是一个词典列表的列表。转换器使用列表推导将其转换为字典列表

然后你可以对其中一个词典进行列表理解,以便通过它迭代顺序:如果项目按顺序存在,则给出所需的输出,否则给出''

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

答案 1 :(得分: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)

答案 2 :(得分: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)

首先创建空列表,然后在列表循环时使用额外信息更新它。

答案 3 :(得分: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', '', '', '']]

答案 4 :(得分:0)

以下解决方案依赖于创建最初使用默认值len(order)填充的维度len(totals) x ''的表格。然后,我们根据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', '', '', '']]