查找列表中是否有三个连续索引在python

时间:2017-04-04 00:07:03

标签: python list

我是蟒蛇初学者,所以我想我可以在这里寻求帮助。

为简单起见,这里有两个输入列表,只有0和1:

 x = [1, 1, 1, 0, 1]
 y = [1, 1, 0, 1, 0]

我试图在python中定义一个逻辑,为x返回True 它有三个连续的元素,它们不等于零;索引0:2都不等于零。 相同的函数不会为y返回任何内容,因为y没有三个连续的元素不等于零。关于指数,我也意味着连续,而不是价值观!

除了解决这个逻辑之外,该函数还应该返回索引和3个非零元素的补丁的最后一个非零元素的值,以防原始条件为真。

所以,让我们说我有一个名为is_three_consecutive_non_zero的假设函数,这里是函数在两种情况下都会返回的函数:

is_three_consecutive_non_zero(x) # should evaluates to (True, 2, 1)

2是三个连续1的组中最后1个的索引,1是非零三个元素的补丁的最后一个非零元素的值!

如果第一个输出为false,则该函数不会返回任何其他内容。

这是一个烦人的三重嵌套for循环函数,有几个if条件可以作为一个很好的起点:

def is_three_consecutive_non_zero(list):
if 0 not in list:
    return True, len(list)-1, list[len(list)-1]

for l in range(0, len(list)):
    for m in range(1, len(list)):
        for n in range(2, len(list)):
            if (l != m) & (m != l) & (n == m + 1) & (m == l + 1):
                if (list[l] != 0) & (list[m] != 0) & (list[n] != 0):
                    return True, n, list[n]

让我们试一试:

is_three_consecutive_non_zero(x)
is_three_consecutive_non_zero(y)

如果您可以分享任何更好的逻辑,或者可能是使用任何其他可用python模块的单个或两个班轮,那将是很棒的。 顺便说一句,这些列表非常小,所以,我不关心时间或空间问题。我也只关心三个非零元素的FIRST PATCH:

z = [0, 1, 1, 1, 1]
is_three_consecutive_non_zero(z) # evaluates to (True, 3, 1) which is consistent with what I want

非常感谢

4 个答案:

答案 0 :(得分:2)

这是你要找的吗?

def f(l):
    for i in range(len(l)-3):
        if all(l[i:i+3]):
            return True, i, l[i+2]
    return False, None, None

如果你只是想回到列表中是否有三个这样的值,那么一个班轮就是any(all(l[i:i+3]) for i in range(len(l)-3))

答案 1 :(得分:2)

您可以使用itertools.groupby对项目进行分组,然后检查非零组的长度。使用enumerate

将索引添加到每个组中的项目
from itertools import groupby

def is_three_consecutive_non_zero(lst):
  for k, g in groupby(enumerate(lst), lambda p: p[1]):
      g = list(g)
      # check that key is not 0 and group length is more than 2
      if k != 0 and len(g) > 2:
          return True, g[-1][0], k


x = [1, 1, 1, 0, 1]
y = [1, 1, 0, 1, 0]
print is_three_consecutive_non_zero(x)
# (True, 2, 1)

print is_three_consecutive_non_zero(y) # should probably return a 3-item tuple
# None

答案 2 :(得分:1)

您可以使用此版本的功能。你可以避免大多数迭代。

def is_three_consecutive_non_zero(list):
  if 0 not in list:
      if len(list)>=3:
          return True, len(list)-1, list[len(list)-1]
  consecutiveNonZero=0
  for index,num in enumerate(list):
      if num is 0:
          consecutiveNonZero = 0
      else:
          consecutiveNonZero = consecutiveNonZero+1
      if consecutiveNonZero>=3:
          return True, index,num
  return False,-1,-1

答案 3 :(得分:0)

使用more_itertools,我们找到所有索引并接受包含连续非零值的大小为n的常规窗口。

import more_itertools as mit


def is_consecutive(seq):
    """Return True if a sequence is consecutively increasing."""
    return tuple(seq) == tuple(range(seq[0], seq[-1]+1))

def consecutive_nonzero(lst, n=3):
    """Return True (bool, index, value) if windows are consecutively non-zero."""
    grouped_idxs = [w for w in mit.windowed(mit.locate(lst), n) if is_consecutive(w)]    # e.g. [(0, 1, 2)]
    return [(True, grp[-1], lst[grp[-1]]) for grp in grouped_idxs]

consecutive_nonzero([1, 1, 1, 0, 1])[0]
# (True, 2, 1)

测试

import nose.tools as nt


def test_consecutive(f):
    """Verify results are consecutive and non-zero."""
    nt.eq_(f([1, 1, 0, 1, 0]), [])
    nt.eq_(f([1, 1, 1, 0, 1]), [(True, 2, 1)])
    nt.eq_(f([1, 1, 1, 0, 1, 1, 1]), [(True, 2, 1), (True, 6, 1)])
    nt.eq_(f([0, 1, 2, 3, 1]), [(True, 3, 3), (True, 4, 1)])
    nt.eq_(f([0, 0, 1, 2, 3, 1, 1, 0], n=5), [(True, 6, 1)])

test_consecutive(f=consecutive_nonzero)