按值从多个列表中删除发生的元素(缩短多个列表)

时间:2014-09-04 02:46:25

标签: python list python-2.7

说我有一份清单清单:

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

我希望最终得到一个列表,该列表会从该列表中的每个列表中删除常见的null / zero / keyword,以产生所需的输出:

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

显然,循环遍历该列表中的每个列表,然后将其与所有其他列表进行比较,这是一个理想的答案。感谢。

2 个答案:

答案 0 :(得分:2)

如果您要排序这些子列表,您会发现最大的子列表将需要从所有这些子列表中删除的零个数。所以只需找到max

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

max(x)
Out[2]: [0, 0, 0, 4, 5, 6]

计算出需要丢弃多少个前导零:

from itertools import takewhile

#needlessly pedantic way of doing this
num_zeroes = len(list(takewhile(lambda p: p == 0, max(x))))

并切片:

[li[num_zeroes:] for li in x]
Out[12]: [[1, 2, 3], [4, 5, 6], [0, 7, 8], [0, 0, 9]]

答案 1 :(得分:1)

  

显然,循环遍历该列表中的每个列表,然后将其与所有其他列表进行比较,这是一个理想的答案。

嗯,没有办法将前缀与每个列表的前缀进行比较。

但是您可以避免将每个列表与每个列表进行比较。换句话说,你可以使这个O(NM),其中M是公共前缀的长度,而不是O(N ** 2)。只需要两遍,跟踪到目前为止在第一遍中看到的最长前缀,然后在第二遍中使用结果。

或者,我们可以使其更明确,为每个列表计算最大值的非零前缀。很明显,这是相同数量的步骤(尽管它会以较小的常数缓慢,因为它在Python中而不是在C中执行内部循环):

def first_nonzero(seq, stop=None):
    for i, val in enumerate(seq):
        if val or i == stop:
            return i
    return i

prefix = None
for lst in list_o_lists:
    prefix = first_nonzero(lst, prefix)

output = [lst[prefix:] for lst in list_o_lists]