bitwise OR reduction of python lists

天涯浪子 提交于 2020-06-23 20:29:15

问题


I have two lists of zeros and ones. Both lists are of same length. The following is just an example, i am looking for a generic solution for lists of any sizes and with zeros and ones at any index.

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

The goal is to use the first list l1 as mask to create a new list l2_new from l2 that logicaly OR merges all elements of indizes where l1 is 1 and adopts elements unchanged where l1 is 0.

Which would result to:

l2_new = [0,0,1]

Graphical explanation:


回答1:


That's a perfect setup for np.bitwise_or.reduceat that does slice-based OR-ing -

# Get slice start indices, needed for `np.bitwise_or.reduceat`
In [55]: idx = np.flatnonzero(np.r_[True,np.diff(l1)!=0])

In [56]: np.bitwise_or.reduceat(l2, idx)
Out[56]: array([0, 0, 1])



回答2:


This should work. Approach is simple.

Wherever you find 1, check for consecutive 1's and mark the start, end index. OR the entries for this range from l2.

Wherever you find 0, copy the respective element from 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)



回答3:


One way is to use 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]



回答4:


This might help; a simple loop without a lot of additional variables.

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)



回答5:


Similar to the answer by @ExplodingGayFish, but I apply groupby on both lists at the same time, and use functional approach to calculate 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]


来源:https://stackoverflow.com/questions/62447168/bitwise-or-reduction-of-python-lists

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!