如果列表包含布尔值,如何从列表中获取整数的索引?

时间:2015-06-15 10:40:24

标签: python list indexing

我刚开始使用Python。

如果列表在1之前包含布尔True对象,如何从列表中获取整数1的索引?

>>> lst = [True, False, 1, 3]
>>> lst.index(1)
0
>>> lst.index(True)
0
>>> lst.index(0)
1

我认为Python在0方法的参数中将False视为1True视为index。如何获得整数1的索引(即2)?

在列表中以这种方式处理布尔对象的原因是什么? 从解决方案来看,我可以看出它并不那么简单。

4 个答案:

答案 0 :(得分:13)

documentation

  

列表是可变序列,通常用于存储集合   同质物品(其中精确的相似程度会因此而异   应用程序)。

您不应将异构数据存储在列表中。 list.index的实施仅使用Py_EQ==运算符)执行比较。在您的情况下,比较返回真值,因为TrueFalse分别具有整数1和0的值(毕竟the bool class is a subclass of int)。

但是,您可以使用生成器表达式和built-in next function(从生成器获取第一个值),如下所示:

In [4]: next(i for i, x in enumerate(lst) if not isinstance(x, bool) and x == 1)
Out[4]: 2

在比较x到1之前,我们会检查bool是否为x 的实例。

请注意,next可以引发StopIteration,在这种情况下,可能需要(重新)引发ValueError(以模仿list.index的行为)

将此全部包装在一个函数中:

def index_same_type(it, val):
    gen = (i for i, x in enumerate(it) if type(x) is type(val) and x == val)
    try:
        return next(gen)
    except StopIteration:
        raise ValueError('{!r} is not in iterable'.format(val)) from None

一些例子:

In [34]: index_same_type(lst, 1)
Out[34]: 2

In [35]: index_same_type(lst, True)
Out[35]: 0

In [37]: index_same_type(lst, 42)
ValueError: 42 is not in iterable

答案 1 :(得分:8)

Booleans 整数的Python,这就是为什么你可以像任何整数一样使用它们:

>>> 1 + True
2
>>> [1][False]
1

[这并不意味着你应该:)]

这是因为boolint的子类,并且几乎总是布尔值的行为就像0或1(除非它被转换为字符串 - 你会得到{ {1}}和"False"代替。)

还有一个想法是如何实现您想要的(但是,尝试重新考虑您的逻辑,并考虑上述信息):

"True"

此代码重新定义了>>> class force_int(int): ... def __eq__(self, other): ... return int(self) == other and not isinstance(other, bool) ... >>> force_int(1) == True False >>> lst.index(force_int(1)) 2 方法,该方法用于比较int方法中的元素,以忽略布尔值。

答案 2 :(得分:5)

以下是使用mapzip的非常简单的天真单线解决方案:

>>> zip(map(type, lst), lst).index((int, 1))
2

在这里,我们映射每个元素的类型,并通过使用元素压缩类型来创建新列表,并请求(type, value)的索引。

这是一个使用相同技术的通用迭代解决方案:

>>> from itertools import imap, izip
>>> def index(xs, x):
...     it = (i for i, (t, e) in enumerate(izip(imap(type, xs), xs)) if (t, e) == x)
...     try:
...             return next(it)
...     except StopIteration:
...             raise ValueError(x)
... 
>>> index(lst, (int, 1))
2

这里我们基本上做了相同的事情但迭代地这样做,以免在内存/空间效率方面花费太多。我们是上面相同表达式的迭代器,但是使用imapizip来构建一个自定义索引函数,它返回迭代器中的下一个值,如果没有,则引发ValueError匹配。

答案 3 :(得分:0)

尝试这个。

for i, j in enumerate([True, False, 1, 3]):
    if not isinstance(j, bool) and j == 1:
        print i

输出:

2