Pythonic way to count specific neighbors in a list

喜你入骨 提交于 2020-01-04 05:19:12

问题


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

  1. First method utilises sum with a generation expression and zip to loop pairwise elements.
  2. Second method is similar to the first but performs better as it avoids building a second list explicitly.
  3. 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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!