繁体   English   中英

查找列表中的第一个元素,其中所有后续值都递增一个

[英]Find the first element in a list where all subsequent values increment by one

我想在列表中找到该值,之后所有其他值仅增加 1。

# Input
my_list1 = [2, 5, 7, 8, 9, 10, 11, 12, 13, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24]
my_list2 = [6, 7, 9, 11, 12, 14, 16, 17, 18, 20, 21, 22, 23, 24, 25, 26, 27, 28]
my_list3 = [5, 6, 7, 8, 9, 11, 12, 13, 15, 16, 18, 19, 20, 21, 22, 23, 24, 25]
# Output
my_list1 = 15
my_list2 = 20
my_list3 = 18

我正在考虑在列表中向后循环,当减少量大于 1 时,在此 position 处提取值。

for x in reversed(my_list1):
    if x decrease > 1:
        print(x)

这是一个基于itertools的工具,如果我们有一个长的列表很有用,所以我们没有将它加载到 memory 中。 这里dropwhile将在条件成立时从可迭代对象中删除值,我们只需要获取结果可迭代对象中的next元素。 请注意, next有一个默认参数,我们可以将其设置为None以避免引发StopIteration错误:

from itertools import tee, dropwhile

def first_diff(it):
    i, j = tee(reversed(it), 2)
    next(j)
    return next((dropwhile(lambda e: e==(next(j)+1), i)), None)

first_diff(my_list1)
# 15
first_diff(my_list2)
# 20
first_diff(my_list3)
# 18

您可以将reversed()列表zip()成对,然后使用next()获取差异大于 1 的第一对。然后我们可以从结果中解压缩第一项。

def first_diff_pair(lst):
    return next(
        (fst for fst, snd in zip(reversed(lst), reversed(lst[:-1])) if fst - snd > 1),
        None,
    )

为了避免next()在没有找到结果并且迭代器耗尽时返回StopIteration ,我们可以将默认值设置为None

Output:

>>> first_diff_pair([2, 5, 7, 8, 9, 10, 11, 12, 13, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24])
15
>>> first_diff_pair([6, 7, 9, 11, 12, 14, 16, 17, 18, 20, 21, 22, 23, 24, 25, 26, 27, 28])
20
>>> first_diff_pair([5, 6, 7, 8, 9, 11, 12, 13, 15, 16, 18, 19, 20, 21, 22, 23, 24, 25])
18

列表推导有几种可能性。 在这里,我收集每个增加超过 1 的数字,将它们存储在列表中并显示最后一个:

print([my_list1[i+1] for i in range(len(my_list1)-1) if my_list1[i+1] - my_list1[i] > 1][-1])
print([my_list2[i+1] for i in range(len(my_list2)-1) if my_list2[i+1] - my_list2[i] > 1][-1])
print([my_list3[i+1] for i in range(len(my_list3)-1) if my_list3[i+1] - my_list3[i] > 1][-1])

好吧,我试过了,它奏效了,但也许还有更好、更有效的解决方案,

l = len(my_list1) - 1
for x in reversed(my_list1):
    if my_list1[l] - my_list1[l - 1] == 1:
      l -= 1
      continue
    else:
      print(x)
      break

这是一个没有重复代码的解决方案:

my_list1 = [2, 5, 7, 8, 9, 10, 11, 12, 13, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24]
my_list2 = [6, 7, 9, 11, 12, 14, 16, 17, 18, 20, 21, 22, 23, 24, 25, 26, 27, 28]
my_list3 = [5, 6, 7, 8, 9, 11, 12, 13, 15, 16, 18, 19, 20, 21, 22, 23, 24, 25]

def getIncreaseStartPoint(nums):
  i = len(nums) - 1
  while (nums[i] - nums[i - 1] == 1):
    i -= 1
    if (i == 0):
      return nums[0]
  return nums[i]

print("mylist_1 =", getIncreaseStartPoint(my_list1))
print("mylist_2 =", getIncreaseStartPoint(my_list2))
print("mylist_3 =", getIncreaseStartPoint(my_list3))

这是一个基本的基于循环的实现。

def get_first_diff(my_list):
    reversed_iter = reversed(my_list)
    last = next(reversed_iter)
    for v in reversed_iter:
        if last - v != 1:
           return last
        last = v
    return None

这是我的尝试:

my_list1 = [2, 5, 7, 8, 9, 10, 11, 12, 13, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24]

tmplist = [x - i for i, x in enumerate(my_list1)]
first = my_list1[tmplist.index(tmplist[-1])]
# result 15

这个怎么运作:

# tmplist is [2, 4, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6]

重复数字显示原始列表中增加序列(+1)的位置。 最后一项 ( tmplist[-1] ) 是 6,我们想要获得第一个此类项目 ( tmplist.index(...) ) 的 position,因为序列从那里开始。 最后,我们查找该索引处的值( my_list1[...]

基于序列中缺失数字的拆分列表类似,您可以使用itertools.groupby对数字的连续运行进行分组,并从那里获取最后一次运行的第一个值:

from itertools import groupby

my_list = [2, 5, 7,8,9,10,11,12,13, 15,16,17,18,19,20,21,22,23,24]
first_value = None
for _, group in groupby(enumerate(my_list), lambda x: x[1] - x[0]):
    first_value = next(group)[1]
print(first_value)
# 15

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM