问题
I have a list. For example:
[0, 0, 1, 0, 0, 1, 0]
I'd like to know what is the most effective way to count the 1 -> 0 transitions. In this case for example the answer is 2 (in the 2-3 and in the 5-6 positions)
I tried the following:
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)])
I'm wondering if there is a better way
回答1:
Here are 3 ways:
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
Explanation
- First method utilises
sum
with a generation expression andzip
to loop pairwise elements. - Second method is similar to the first but performs better as it avoids building a second list explicitly.
- Third method utilises the 3rd party
numpy
library and is a vectorised approach.
回答2:
Transforming your input data with slices and zips and cuts and folds is one way to approach it. And it's awesome to see how these generic actions can be combined to build a machine that represents our intended action, even if it arrives at the desired result in a roundabout way.
However, I think a more direct approach yields a more natural program. You can express your intention using natural descriptors and operations. Another benefit is you can more clearly visualize the space-time requirements of the process your function creates. Ie, it's easy to see switches
below runs in O(n)
; comparatively, it's very hard to estimate space-time requirements of the "machine" implementation.
A simple recursive function
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 :(
Above, the answer is 4
because it's counting switches from 0 to 1 and switches from 1 to 0. You only want to count switches in one direction. We could modify our function like this
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 :)
But you can see there's a clever way to condense the conditional
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:
You can use 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))
Output:
2
来源:https://stackoverflow.com/questions/49680611/pythonic-way-to-count-specific-neighbors-in-a-list