如何在Python中遍历列表时去除None

3
我有两个不相等的列表,我正在使用itertools遍历它们,并尝试使用filter函数来删除List1中生成的None,以便最终a仅包含两个元素而不是三个(计算None)。但是我一直收到此错误:Type error: NoneType object is not iterable。
import itertools

List1  = [['a'],['b']]
List2 = ['A','b','C']

l = list(itertools.chain(*List1))
print(l)

for a, b in itertools.zip_longest((b for a in List1 for b in a),List2):
    filter(None, a)
    print(a,b)

1
你为什么要使用zip_longestzip不已经完全满足你的需求了吗? - user2357112
a只是一个元素,不是列表,并且最后是None。另外,如果你想要“过滤掉”None,那么在b的第三个元素中,a将会是什么?可以使用带有Nonezip_longest或者只使用zip - tobias_k
@tobias_k 这就是问题所在,我想要第三个元素,但我不想让a有一个值。事实上,我正在实现的真正列表由对象组成,因此尝试获取None的属性会抛出异常,说该对象没有该属性。 - danidee
我想要第三个元素,但我不想让a有一个值。那么,你想让那个元素是什么呢?None似乎是一个不错的选择,你只需要在对它进行操作之前检查它是否为None。另一种变体可能是使用你的类的特殊实例作为哨兵值,而不是None - tobias_k
3个回答

3

我不是完全清楚你想要什么。根据我的理解,你想使用izip_longest来合并列表,但结果中没有任何None元素。

这将从列表的'切片'中过滤掉None,并仅打印非None值。但请注意,这种方式无法确定例如non_none列表中的第一个元素是来自第一个列表、第二个列表还是第三个列表。

a = ["1", "2"]
b = ["a", "b", "c", "d"]
c = ["x", "y", "z"]

for zipped in izip_longest(a, b, c):
    non_none = filter(None, zipped)
    print non_none

输出:

('1', 'a', 'x')
('2', 'b', 'y')
('c', 'z')
('d',)

顺便提一下,filter(None, a) 的作用:它从你的a中过滤掉None值,即从字符串"a""b"中过滤掉None值(这不会有太大的影响,因为它们不包含None值),直到最后一个值失败,因为None不可迭代。此外,它无论如何都会丢弃结果,因为您没有将其绑定到变量上。filter不会修改原始列表,而是返回一个过滤后的副本!


FILTER将0和None视为等效,因此对于用户的目的(如果0很重要)结果可能不正确。在这种情况下,使用filter(lambda x: x if x is not None, zipped)是一个“更好”的答案(忽略内存、速度等目标)。 - lb_so

2
为什么不直接使用zip
for a, b in zip((b for a in List1 for b in a),List2):
    print(a,b)

然而,如果您真的坚持使用zip_longest,您不需要使用filter来删除None值。您只需要使用一个if语句。

for a, b in itertools.zip_longest((b for a in List1 for b in a),List2):
    if a is None: continue
    print(a,b)

我认为这个建议不足够“强大”,因为zip和zip_longest可以并且将用于不止两个列表。对于n > 2的情况,使用这种方法会非常麻烦,不是吗?我认为在压缩后过滤或重建列表以排除None值是唯一可行的方法。 - lb_so

0
import itertools as it

def grouper(inputs, n, fillvalue=None):
    iters = [iter(inputs)] * n
    interim = it.zip_longest(*iters, fillvalue=fillvalue)
    return interim

nums = range(23)
results = (list(grouper(nums, 4)))

finalanswer = []
for zipped in results:
    # non_none = tuple(filter(None, zipped))
    # unfortunately the line above filters 0 which is incorrect so instead use:
    non_none = tuple(filter(lambda x: x is not None, zipped))
    finalanswer.append(non_none)
print(finalanswer)

上面的代码使用zip_longest来说明如何生成“n”个列表的压缩迭代,无论给定列表中是否存在相应的条目,然后剥离出“None”值。需要注意的是,FILTER将None和0视为等效的,因此必须使用“lambda”版本。

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