压缩 python 列表中所有连续的
squash all consecutive ones in a python list
我有包含 0s
和 1s
的变量列表,例如:
l1 = [1,1,1,0,1,1]
l2 = [0,1,1,0,1,1,0,0,1]
创建压缩所有连续 1s
.
的新列表的最有效方法是什么
所以结果是:
l1_new = [1,0,1]
l2_new = [0,1,0,1,0,0,1]
Hint: numpy/vectorization or some logical operation would be great!
这是一个可能的解决方案
arr = [0,1,1,0,1,1,0,0,1]
previous_value = None
new_lst = []
for elem in arr:
if elem != previous_value:
new_lst.append(elem)
previous_value = elem
print(new_lst)
其中 arr
是您想要的任何列表,它适用于包括字符串在内的任何内容。
要利用 NumPy,我们需要数组,因此在转换后,我们将创建适当的掩码和索引 -
def squash1s(a):
a = np.asarray(a)
m = a==1
return a[np.r_[True,m[:-1]!=m[1:]] | (a==0)]
样本运行 -
In [64]: l1 = [1,1,1,0,1,1]
...: l2 = [0,1,1,0,1,1,0,0,1]
In [65]: squash1s(l1)
Out[65]: array([1, 0, 1])
In [66]: squash1s(l2)
Out[66]: array([0, 1, 0, 1, 0, 0, 1])
基准测试
由于我们关心的是性能效率,所以让我们对 NumPy 进行基准测试,因为它们应该非常高效。
其他建议的解决方案
# @yatu's solution
def yatu_diff(l):
a = np.asarray(l)
return a[~((np.diff(a,prepend=False)==0) & a==1)]
# PaulPanzer's suggestion/soln
def pp_concat(a):
a = np.asarray(a)
return a.repeat(1-(a*np.concatenate([[0],a[:-1]])))
使用 benchit
包(几个基准测试工具打包在一起;免责声明:我是它的作者)对提议的解决方案进行基准测试。
import benchit
funcs = [squash1s, yatu_diff, pp_concat]
# With ~30% 0s
in_ = [(np.random.rand(n)>0.3).astype(int) for n in 10**np.arange(4)]
t = benchit.timings(funcs, in_)
t.plot(logx=True, save='timings30.png')
# With ~70% 0s
in_ = [(np.random.rand(n)>0.7).astype(int) for n in 10**np.arange(4)]
t = benchit.timings(funcs, in_)
t.plot(logx=True, save='timings70.png')
有 ~30%
0s :
有 ~70%
0s :
使用 while 循环,
l1 = [1,1,1,0,1,1]
i = 0
while i < len(l1)-1:
if l1[i] == l1[i+1]:
del l1[i]
else:
i = i+1
print(l1)
我在 geeksforgeeks 上找到的另一个是,
from itertools import zip_longest
test_list = [1, 4, 4, 4, 5, 6, 7, 4, 3, 3, 9]
res = [i for i, j in zip_longest(test_list, test_list[1:])
if i != j]
这是使用 np.diff
和 bitwise operations
的一种方法:
l1 = [1,1,1,0,1,1]
l2 = [0,1,1,0,1,1,0,0,1]
a = np.array(l2)
a[~((np.diff(a,prepend=False)==0) & (a==1))]
# array([0, 1, 0, 1, 0, 0, 1])
或者第一个例子:
a = np.array(l1)
a[~((np.diff(a,prepend=False)==0) & (a==1))]
#array([1, 0, 1])
给定
lst_1 = [1, 1, 1, 0, 1, 1]
lst_2 = [0, 1, 1, 0, 1, 1, 0, 0, 1]
lst_3 = [0, 1, 1, 0, 1, 1, 0, 0, 1, 1]
代码
def compress_values(seq, value=1):
"""Yield a value in isolation."""
for here, nxt in zip(seq, seq[1:]):
if here == nxt == value:
continue
else:
yield here
yield nxt
演示
assert [1, 0, 1] == list(compress_values(lst_1))
assert [0, 1, 0, 1, 0, 0, 1] == list(compress_values(lst_2))
assert [0, 1, 0, 1, 0, 0, 1] == list(compress_values(lst_3))
详情
滑动一个二元组window。如果值彼此相等且目标 value
,则跳过。否则产生值。
另一种更通用的方法:
import itertools as it
def squash(seq, values=(1,)):
"""Yield singular values in isolation."""
for k, g in it.groupby(seq):
if k in values:
yield k
else:
yield from g
我有包含 0s
和 1s
的变量列表,例如:
l1 = [1,1,1,0,1,1]
l2 = [0,1,1,0,1,1,0,0,1]
创建压缩所有连续 1s
.
所以结果是:
l1_new = [1,0,1]
l2_new = [0,1,0,1,0,0,1]
Hint: numpy/vectorization or some logical operation would be great!
这是一个可能的解决方案
arr = [0,1,1,0,1,1,0,0,1]
previous_value = None
new_lst = []
for elem in arr:
if elem != previous_value:
new_lst.append(elem)
previous_value = elem
print(new_lst)
其中 arr
是您想要的任何列表,它适用于包括字符串在内的任何内容。
要利用 NumPy,我们需要数组,因此在转换后,我们将创建适当的掩码和索引 -
def squash1s(a):
a = np.asarray(a)
m = a==1
return a[np.r_[True,m[:-1]!=m[1:]] | (a==0)]
样本运行 -
In [64]: l1 = [1,1,1,0,1,1]
...: l2 = [0,1,1,0,1,1,0,0,1]
In [65]: squash1s(l1)
Out[65]: array([1, 0, 1])
In [66]: squash1s(l2)
Out[66]: array([0, 1, 0, 1, 0, 0, 1])
基准测试
由于我们关心的是性能效率,所以让我们对 NumPy 进行基准测试,因为它们应该非常高效。
其他建议的解决方案
# @yatu's solution
def yatu_diff(l):
a = np.asarray(l)
return a[~((np.diff(a,prepend=False)==0) & a==1)]
# PaulPanzer's suggestion/soln
def pp_concat(a):
a = np.asarray(a)
return a.repeat(1-(a*np.concatenate([[0],a[:-1]])))
使用 benchit
包(几个基准测试工具打包在一起;免责声明:我是它的作者)对提议的解决方案进行基准测试。
import benchit
funcs = [squash1s, yatu_diff, pp_concat]
# With ~30% 0s
in_ = [(np.random.rand(n)>0.3).astype(int) for n in 10**np.arange(4)]
t = benchit.timings(funcs, in_)
t.plot(logx=True, save='timings30.png')
# With ~70% 0s
in_ = [(np.random.rand(n)>0.7).astype(int) for n in 10**np.arange(4)]
t = benchit.timings(funcs, in_)
t.plot(logx=True, save='timings70.png')
有 ~30%
0s :
有 ~70%
0s :
使用 while 循环,
l1 = [1,1,1,0,1,1]
i = 0
while i < len(l1)-1:
if l1[i] == l1[i+1]:
del l1[i]
else:
i = i+1
print(l1)
我在 geeksforgeeks 上找到的另一个是,
from itertools import zip_longest
test_list = [1, 4, 4, 4, 5, 6, 7, 4, 3, 3, 9]
res = [i for i, j in zip_longest(test_list, test_list[1:])
if i != j]
这是使用 np.diff
和 bitwise operations
的一种方法:
l1 = [1,1,1,0,1,1]
l2 = [0,1,1,0,1,1,0,0,1]
a = np.array(l2)
a[~((np.diff(a,prepend=False)==0) & (a==1))]
# array([0, 1, 0, 1, 0, 0, 1])
或者第一个例子:
a = np.array(l1)
a[~((np.diff(a,prepend=False)==0) & (a==1))]
#array([1, 0, 1])
给定
lst_1 = [1, 1, 1, 0, 1, 1]
lst_2 = [0, 1, 1, 0, 1, 1, 0, 0, 1]
lst_3 = [0, 1, 1, 0, 1, 1, 0, 0, 1, 1]
代码
def compress_values(seq, value=1):
"""Yield a value in isolation."""
for here, nxt in zip(seq, seq[1:]):
if here == nxt == value:
continue
else:
yield here
yield nxt
演示
assert [1, 0, 1] == list(compress_values(lst_1))
assert [0, 1, 0, 1, 0, 0, 1] == list(compress_values(lst_2))
assert [0, 1, 0, 1, 0, 0, 1] == list(compress_values(lst_3))
详情
滑动一个二元组window。如果值彼此相等且目标 value
,则跳过。否则产生值。
另一种更通用的方法:
import itertools as it
def squash(seq, values=(1,)):
"""Yield singular values in isolation."""
for k, g in it.groupby(seq):
if k in values:
yield k
else:
yield from g