简体   繁体   English

Python-填补列表中的空白

[英]Python - filling gaps in list

I have a list made of tuples, generated from a database query, eg: 我有一个由元组组成的列表,是从数据库查询生成的,例如:

list = [(0,1,1), (1,2,1), (2,4,3), (4,2,1)]

The first number in each tuple must be a consecutive number, going from 0 to 15. There may also be missing ones, and I'm looking for the best method to fill gaps. 每个元组中的第一个数字必须是一个连续的数字,从0到15。可能还会有一些缺失的数字,我正在寻找填补空白的最佳方法。

Currently I do this by looping through, but being the Python noob I am I figure it's sloppy and there's better ways: 目前,我是通过循环来完成此操作的,但是作为Python noob,我认为它很草率,并且有更好的方法:

# first fill in gaps
cnt = 0
for a,b,c in list:
    if a > cnt:
        list.insert(cnt, tuple((cnt, 0, 0)))
    cnt += 1

# then add any missing at end
while cnt < 16:
    list.append(tuple((cnt, 0, 0)))
    cnt += 1

So, expected output for the list at start would be: 因此,列表开始时的预期输出为:

list = [(0,1,1), (1,2,1), (2,4,3), (3,0,0), (4,2,1), (5,0,0), (6,0,0), (7,0,0), (8,0,0), (9,0,0), (10,0,0), (11,0,0), (12,0,0), (13,0,0), (14,0,0), (15,0,0)]

There are many ways, you could generate a new list like this: 有很多方法,您可以像这样生成一个新列表:

data = [(0,1,1), (1,2,1), (2,4,3), (4,2,1)]

out = []
for i in range(16):
    if data and i == data[0][0]:
        out.append(data.pop(0))
    else:
        out.append((i, 0, 0))

print(out)
# [(0, 1, 1), (1, 2, 1), (2, 4, 3), (3, 0, 0), (4, 2, 1), 
# (5, 0, 0), (6, 0, 0), (7, 0, 0), (8, 0, 0), (9, 0, 0), 
# (10, 0, 0), (11, 0, 0), (12, 0, 0), (13, 0, 0), (14, 0, 0), (15, 0, 0)]

As a side note, I renamed your list data , as it is better to avoid using the names of builtin functions as variables. 附带说明一下,我重命名了列表data ,因为最好避免将内置函数的名称用作变量。

You can convert the list of tuples to a dict indexed by the first items of the tuples first, so that you can iterate through the range of 0 to 15 to find the missing indices and produce default values for them in a list comprehension: 您可以将元组列表转换为首先由元组的第一项索引的字典,以便您可以迭代0到15的范围以找到缺失的索引,并在列表理解中为其生成默认值:

l = [(0,1,1), (1,2,1), (2,4,3), (4,2,1)]
d = {k: v for k, *v in l}
print([(i, *d.get(i, (0, 0))) for i in range(16)])

This outputs: 输出:

[(0, 1, 1), (1, 2, 1), (2, 4, 3), (3, 0, 0), (4, 2, 1), (5, 0, 0), (6, 0, 0), (7, 0, 0), (8, 0, 0), (9, 0, 0), (10, 0, 0), (11, 0, 0), (12, 0, 0), (13, 0, 0), (14, 0, 0), (15, 0, 0)]

In order to introduce some interesting language features, that can be used to solve this, here a solution based on Python's stable sort with a simple sort key function and itertools.groupby() to group the items based on the index. 为了介绍一些有趣的语言功能(可用于解决此问题),这里提供了一种基于Python稳定排序的解决方案,该解决方案具有简单的排序键函数和itertools.groupby() ,可根据索引对项目进行分组。

You then take the first of two, if you had this index in the input data. 然后,如果输入数据中有此索引,则取两个中的第一个。 Or the default item, if there was none with this index. 如果没有此索引,则为默认项。

import itertools

received_items = [(0,1,1), (1,2,1), (2,4,3), (4,2,1)]
print(received_items)

default_items = [(i, 0, 0) for i in range(16)]

# append default items at the end
data = received_items + default_items
# perform stable sort on the index (first element) selected via key function
keyfunc = lambda x: x[0]
data.sort(key=keyfunc)
# always take first item for each index group
out = [next(v) for k,v in itertools.groupby(data, key=keyfunc)]

print(out)

The output is: 输出为:

[(0, 1, 1), (1, 2, 1), (2, 4, 3), (4, 2, 1)]
[(0, 1, 1), (1, 2, 1), (2, 4, 3), (3, 0, 0), (4, 2, 1), (5, 0, 0), (6, 0, 0), (7, 0, 0), (8, 0, 0), (9, 0, 0), (10, 0, 0), (11, 0, 0), (12, 0, 0), (13, 0, 0), (14, 0, 0), (15, 0, 0)]

For reference: 以供参考:

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM