sau*_*aud 15 python boolean list python-3.x
我有一个很长的布尔数组:
bool_array = [ True, True, True, True, True, False, False, False, False, False, True, True, True, False, False, True, True, True, True, False, False, False, False, False, False, False ]
Run Code Online (Sandbox Code Playgroud)
我需要找出值翻转的位置,即,序列True和False开始的地址.在这种特殊情况下,我想得到
index = [0, 5, 10, 13, 15, 19, 26]
Run Code Online (Sandbox Code Playgroud)
有没有一种简单的方法可以不用手动循环来检查第(i + 1)行的每个第i个元素?
Kas*_*mvd 17
对于大型数据集更有效的方法,在Python 3.X可以使用accumulate并 groupby从功能itertools模块.
>>> from itertools import accumulate, groupby
>>> [0] + list(accumulate(sum(1 for _ in g) for _,g in groupby(bool_array)))
[0, 5, 10, 13, 15, 19, 26]
Run Code Online (Sandbox Code Playgroud)
代码背后的逻辑:
此代码使用groupby()函数对连续的重复项进行分类,然后循环返回的迭代器,该迭代器groupby()包含成对的键(我们使用线下而不是丢弃的变量将其转义)和这些分类的迭代器.
>>> [list(g) for _, g in groupby(bool_array)]
[[True, True, True, True, True], [False, False, False, False, False], [True, True, True], [False, False], [True, True, True, True], [False, False, False, False, False, False, False]]
Run Code Online (Sandbox Code Playgroud)
所以我们所需要的只是计算这些迭代器的长度,并将每个长度与其先前的长度相加,以便获得第一项的索引,该索引恰好是项目的更改位置,这正是该accumulate()函数的用途.
在Numpy中,您可以使用以下方法:
In [19]: np.where(arr[1:] - arr[:-1])[0] + 1
Out[19]: array([ 5, 10, 13, 15, 19])
# With leading and trailing indices
In [22]: np.concatenate(([0], np.where(arr[1:] - arr[:-1])[0] + 1, [arr.size]))
Out[22]: array([ 0, 5, 10, 13, 15, 19, 26])
Run Code Online (Sandbox Code Playgroud)
Dil*_*rix 12
这将告诉你在哪里:
>>> import numpy as np
>>> np.argwhere(np.diff(bool_array)).squeeze()
array([ 4, 9, 12, 14, 18])
Run Code Online (Sandbox Code Playgroud)
np.diff计算每个元素和下一个元素之间的差异.对于布尔值,它实质上将值解释为整数(0:False,非零:True),因此差异显示为+1或-1值,然后将其映射回布尔值(当存在更改时为True).
np.argwhere然后该函数告诉您值为True的位置 - 现在是更改.
>>> [i for i,(m,n) in enumerate(zip(bool_array[:-1],bool_array[1:])) if m!=n]
[4, 9, 12, 14, 18]
Run Code Online (Sandbox Code Playgroud)
既然你有[4, 9, 12, 14, 18],你可以
>>> [0]+[i+1 for i in [4, 9, 12, 14, 18]]+[len(bool_array)]
[0, 5, 10, 13, 15, 19, 26]
Run Code Online (Sandbox Code Playgroud)
实现你的输出.
代码背后的逻辑:
zip接受两个迭代器并返回两个元素的序列.我们为从第一个元素开始的迭代器和从第二个元素开始的迭代器传递相同的列表.因此,我们得到一个相邻数字列表enumerate 为您提供一系列索引和迭代器的值.另一个单步程序是
>>> [i for i,(m,n) in enumerate(zip([2]+bool_array,bool_array+[2])) if m!=n]
[0, 5, 10, 13, 15, 19, 26]
Run Code Online (Sandbox Code Playgroud)
这里我们故意引入[2]列表,这是因为第一个和最后一个值将始终不同([2]从未在列表中出现).因此我们将直接获得这些索引.
| 归档时间: |
|
| 查看次数: |
1550 次 |
| 最近记录: |