python 列表的按位或缩减
bitwise OR reduction of python lists
我有两个零和一个列表。两个列表的长度相同。以下只是一个例子,我正在寻找一个通用的解决方案,用于任何大小的列表以及任何索引处的零和一。
l1 = [1,1,0,1,1,1,1]
l2 = [0,0,0,1,0,0,0]
目标是使用第一个列表 l1
作为 mask
从 l2
创建一个新列表 l2_new
逻辑上 OR
合并所有元素indizes 其中 l1
是 1
并采用不变的元素,其中 l1
是 0
.
这将导致:
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)))
我有两个零和一个列表。两个列表的长度相同。以下只是一个例子,我正在寻找一个通用的解决方案,用于任何大小的列表以及任何索引处的零和一。
l1 = [1,1,0,1,1,1,1]
l2 = [0,0,0,1,0,0,0]
目标是使用第一个列表 l1
作为 mask
从 l2
创建一个新列表 l2_new
逻辑上 OR
合并所有元素indizes 其中 l1
是 1
并采用不变的元素,其中 l1
是 0
.
这将导致:
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)))