高效地将列表合并为稀疏列表

7

我有两个列表:

a = [None, None, 1, None, 4, None, None, 5, None]
b = [7,8,2,3,6,9]

我希望你能帮我将它们合并,可以创建一个新列表或者只是更新a,通过用b中的值填充Nones。因此:
a = [7,8,1,2,4,3,6,5,9]

最高效的方法是什么?

对于扩展,我将希望对b的每个排列都执行此操作。这是否允许在技术上进行简化?


b 可以包含比必要的元素更少或更多吗? - Mr. T
不需要 - 我们可以假设b的大小是正确的。 - xorsyst
5个回答

6

这是一种方法。使用列表推导式并将b转换为迭代器对象。

示例:

a = [None, None, 1, None, 4, None, None, 5, None]
b = [7,8,2,3,6,9]
b = iter(b)

print( [next(b) if i is None else i for i in a] )

输出:

[7, 8, 1, 2, 4, 3, 6, 5, 9]

3
for reversed_index in range(len(a) - 1, -1, -1):
    if a[reversed_index] is None:
        a[reversed_index] = b.pop()

这段代码应该是高效的,因为它直接在原列表 a 上进行修改,并且从右侧弹出列表也是高效的。据我所知,这是一个 O(len(a)) 的解决方案。


3

使用反转后的第二个b列表上的list.pop()方法:

a = [None, None, 1, None, 4, None, None, 5, None]
b = [7,8,2,3,6,9]
tmp = b[::-1]

result = [tmp.pop() if i is None else i for i in a]
print(result)    # [7, 8, 1, 2, 4, 3, 6, 5, 9]

很棒的解决方案。在我的测试中,迭代器更快,但差距不大。 - xorsyst

1
递归方法:
a = [None, None, 1, None, 4, None, None, 5, None]
b = [7,8,2,3,6,9]

def recursion_approach(first_list,second_list):

    for index,value in enumerate(first_list):
            if value!=None:
                first_list[index]=value
            else:
                first_list[index]=second_list[0]
                recursion_approach(first_list,second_list[1:])

    return first_list

print(recursion_approach(a,b))

输出:

[7, 8, 1, 2, 4, 3, 6, 5, 9]

优雅的解决方案 - 正如您所预期的那样,它并不是非常快。 - xorsyst

1

为了处理大型列表的性能,您可能会发现第三方库更有效,例如通过Pandas或NumPy。

Pandas

创建2个系列并使用布尔索引进行赋值:

import pandas as pd

a = pd.Series([None, None, 1, None, 4, None, None, 5, None])
b = pd.Series([7,8,2,3,6,9])

a[a.isnull()] = b.values

print(a.values.astype(int).tolist())

# [7, 8, 1, 2, 4, 3, 6, 5, 9]

numpy

如果使用np.nan而不是None,与NumPy类似:

import numpy as np

a = np.array([np.nan, np.nan, 1, np.nan, 4, np.nan, np.nan, 5, np.nan])
b = np.array([7,8,2,3,6,9])

a[np.isnan(a)] = b

# array([ 7.,  8.,  1.,  2.,  4.,  3.,  6.,  5.,  9.])

请参见NumPy相对于普通的Python列表的优势是什么?

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