python 列表的按位或缩减

bitwise OR reduction of python lists

我有两个零和一个列表。两个列表的长度相同。以下只是一个例子,我正在寻找一个通用的解决方案,用于任何大小的列表以及任何索引处的零和一。

l1 = [1,1,0,1,1,1,1]
l2 = [0,0,0,1,0,0,0]

目标是使用第一个列表 l1 作为 maskl2 创建一个新列表 l2_new 逻辑上 OR 合并所有元素indizes 其中 l11 并采用不变的元素,其中 l10.

这将导致:

l2_new = [0,0,1]

图解说明:

这应该有效。 方法很简单。

无论你在哪里找到 1,检查连续的 1 并标记开始、结束索引。或此范围内的条目 l2.

无论你在哪里找到 0,从 l2 复制相应的元素

index = 0

prev = 0
res = []
while index < len(l1):
    if l1[index] == 1:
        prev = index
        while index < len(l1) and l1[index] == 1:
            index += 1

        tmp = 0
        for i in range(prev,index):
            tmp = tmp|l2[i]
        res.append(tmp)

    elif l1[index] == 0:
        res.append(l2[index])
        index += 1

print(res)

一种方法是使用 itertools.groupby:

import itertools 
l1 = [1,1,0,1,1,1,1]
l2 = [0,0,0,1,0,0,0]
pos = [(item, pos) for pos, item in enumerate(l1)]
#[(1, 0), (1, 1), (0, 2), (1, 3), (1, 4), (1, 5), (1, 6)]

result = []
for key, group in itertools.groupby(pos, lambda x: x[0]):
    if key == 0:
        #if group is all 0 then we don't change anything
        result.extend(l2[g[1]] for g in group)
    else:
        #else do OR operation in current group and append to final list
        current = 0
        for g in group:
            current |= l2[g[1]]
        result.append(current)
result
#[0, 0, 1]

这可能会有所帮助;没有很多额外变量的简单循环。

l1 = [1, 1, 0, 1, 1, 1, 1]
l2 = [0, 0, 0, 1, 0, 0, 0]

answer = []
or_result = 0
index = 0

while index < len(l1):
    # while 1, OR the elements of l2
    while index < len(l1) and l1[index] == 1:
        or_result ^= l2[index]
        index += 1

    answer.append(or_result)

    # while 0, append the elements of l2 as they are
    while index < len(l1) and l1[index] == 0:
        answer.append(l2[index])
        index += 1

    or_result = 0

print(answer)

与@ExplodingGayFish 的回答类似,但我同时在两个列表上应用 groupby,并使用函数方法计算 OR。

from functools import reduce
from itertools import groupby
from operator import or_


def fn(l1, l2):
    result = []

    # group both lists by the values in l1
    for key, group in groupby(zip(l1, l2), key=lambda x: x[0]):
        # extract values from l2
        group_from_l2 = [x[1] for x in group]
        if key == 1:
            # bitwise OR of all values in group_from_l2
            result.append(reduce(or_, group_from_l2))
        else:
            # group_from_l2 unchanged
            result.extend(group_from_l2)

    return result
>>> fn([1, 1, 0, 1, 1, 1, 1], [0, 0, 0, 1, 0, 0, 0])
[0, 0, 1]
>>> fn([1, 1, 0, 0, 1, 1, 0, 0], [0, 1, 1, 0, 1, 1, 0, 1])
[1, 1, 0, 1, 0, 1]

这是 np.bitwise_or.reduceat 的完美设置,它基于切片 OR-ing -

# Based on  @Divakar
def squash1s_mask(a):
    a = np.asarray(a)
    m = a==1
    return np.r_[True,m[:-1]!=m[1:]] | (a==0)

out = np.bitwise_or.reduceat(l2, np.flatnonzero(squash1s_mask(l1)))