问题
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