计算列表中特定邻居的 Pythonic 方法
Pythonic way to count specific neighbors in a list
我有一个清单。例如:
[0, 0, 1, 0, 0, 1, 0]
我想知道计算 1 -> 0 转换的最有效方法是什么。在这种情况下,例如答案是 2(在 2-3 和 5-6 位置)
我尝试了以下方法:
stat=[0, 0, 1, 0, 0, 1, 0]
pair1=stat[:-1]
pair2=stat[1:]
result=len([i for i in zip(pair1, pair2) if i==(1,0)])
请问有没有更好的方法
使用切片、压缩、剪切和折叠来转换输入数据是一种处理方法。很高兴看到如何将这些通用操作组合起来构建一个代表我们预期操作的机器,即使它以迂回的方式达到了预期的结果。
但是,我认为更直接的方法会产生更自然的程序。您可以使用自然描述符和操作来表达您的意图。另一个好处是您可以更清楚地可视化您的函数创建的流程的 space-time 要求。即,很容易看到下面的 switches
在 O(n)
中运行;相比之下,很难估计 "machine" 实施的 space-time 要求。
一个简单的递归函数
def switches (iter, last = 0):
if not iter:
return 0
first, *rest = iter
if first == last:
return switches (rest, last)
else:
return 1 + switches (rest, first)
print (switches ([ 0, 0, 1, 1, 0, 0, 1, 1, 1, 0 ]))
# 4 :(
上面,答案是4
因为它计算从0到1的开关和从1到0的开关。你只想计算[=26]中的开关=]一个个方向。我们可以像这样修改我们的函数
def switches (iter, last = 0):
if not iter:
return 0
first, *rest = iter
if first == last:
return switches (rest, last)
else:
if first == 1: # only count when switching from 1
return 1 + switches (rest, first)
else:
return 0 + switches (rest, first)
print (switches ([ 0, 0, 1, 1, 0, 0, 1, 1, 1, 0 ]))
# 2 :)
但是你可以看到有一种巧妙的方法来压缩条件
def switches (iter, last = 0):
if not iter:
return 0
first, *rest = iter
if first == last:
return switches (rest, last)
else:
return first + switches (rest, first)
print (switches ([ 0, 0, 1, 1, 0, 0, 1, 1, 1, 0 ]))
# 2 :)
这里有3种方法:
from itertools import islice
import numpy as np
lst = [0, 0, 1, 0, 0, 1, 0]
res1 = sum(i - j == 1 for i, j in zip(lst, lst[1:])) # 2
res2 = sum(i - j == 1 for i, j in zip(lst, islice(lst, 1, None))) # 2
res3 = np.sum(np.diff(lst) == -1) # 2
说明
- 第一种方法使用带有生成表达式的
sum
和 zip
循环成对元素。
- 第二种方法与第一种方法类似,但性能更好,因为它避免了显式构建第二个列表。
- 第三种方法利用第 3 方
numpy
库,是一种矢量化方法。
您可以使用 sum
:
s = [0, 0, 1, 0, 0, 1, 0]
new_s = sum(abs(s[i]-s[i+1]) == 1 for i in range(0, len(s)-1, 2))
输出:
2
我有一个清单。例如:
[0, 0, 1, 0, 0, 1, 0]
我想知道计算 1 -> 0 转换的最有效方法是什么。在这种情况下,例如答案是 2(在 2-3 和 5-6 位置)
我尝试了以下方法:
stat=[0, 0, 1, 0, 0, 1, 0]
pair1=stat[:-1]
pair2=stat[1:]
result=len([i for i in zip(pair1, pair2) if i==(1,0)])
请问有没有更好的方法
使用切片、压缩、剪切和折叠来转换输入数据是一种处理方法。很高兴看到如何将这些通用操作组合起来构建一个代表我们预期操作的机器,即使它以迂回的方式达到了预期的结果。
但是,我认为更直接的方法会产生更自然的程序。您可以使用自然描述符和操作来表达您的意图。另一个好处是您可以更清楚地可视化您的函数创建的流程的 space-time 要求。即,很容易看到下面的 switches
在 O(n)
中运行;相比之下,很难估计 "machine" 实施的 space-time 要求。
一个简单的递归函数
def switches (iter, last = 0):
if not iter:
return 0
first, *rest = iter
if first == last:
return switches (rest, last)
else:
return 1 + switches (rest, first)
print (switches ([ 0, 0, 1, 1, 0, 0, 1, 1, 1, 0 ]))
# 4 :(
上面,答案是4
因为它计算从0到1的开关和从1到0的开关。你只想计算[=26]中的开关=]一个个方向。我们可以像这样修改我们的函数
def switches (iter, last = 0):
if not iter:
return 0
first, *rest = iter
if first == last:
return switches (rest, last)
else:
if first == 1: # only count when switching from 1
return 1 + switches (rest, first)
else:
return 0 + switches (rest, first)
print (switches ([ 0, 0, 1, 1, 0, 0, 1, 1, 1, 0 ]))
# 2 :)
但是你可以看到有一种巧妙的方法来压缩条件
def switches (iter, last = 0):
if not iter:
return 0
first, *rest = iter
if first == last:
return switches (rest, last)
else:
return first + switches (rest, first)
print (switches ([ 0, 0, 1, 1, 0, 0, 1, 1, 1, 0 ]))
# 2 :)
这里有3种方法:
from itertools import islice
import numpy as np
lst = [0, 0, 1, 0, 0, 1, 0]
res1 = sum(i - j == 1 for i, j in zip(lst, lst[1:])) # 2
res2 = sum(i - j == 1 for i, j in zip(lst, islice(lst, 1, None))) # 2
res3 = np.sum(np.diff(lst) == -1) # 2
说明
- 第一种方法使用带有生成表达式的
sum
和zip
循环成对元素。 - 第二种方法与第一种方法类似,但性能更好,因为它避免了显式构建第二个列表。
- 第三种方法利用第 3 方
numpy
库,是一种矢量化方法。
您可以使用 sum
:
s = [0, 0, 1, 0, 0, 1, 0]
new_s = sum(abs(s[i]-s[i+1]) == 1 for i in range(0, len(s)-1, 2))
输出:
2