遍历列表,比较前后元素

1 投票
3 回答
1146 浏览
提问于 2025-04-17 15:48

我正在尝试写一个函数来验证一个列表。

简单来说,对于列表中的每一个元素,它前面或后面的元素必须是相同的。

一个好的列表被定义为:

good_list = ["H", "H", "H", "M", "M", "L", "L", "M", "M", "H", "H", "H"]

一个坏的列表被定义为:

bad_list = ["H", "M", "H", "M", "M", "L", "L", "M", "M", "H", "H", "H"]

我花了几天时间尝试不同的解决方案(还在stackoverflow上查了资料),下面是我目前的代码,但它没有返回正确的答案。根据反馈(谢谢大家!),我更新了代码,把参数的名字从list改成了season,并且做了一个“或”的判断。不过它还是在不应该返回“有效列表”的情况下返回了这个结果?

bad_list = ["H", "M", "H", "M", "M", "L", "L", "M", "M", "H", "H", "H"]

def check_list(season):     
   for i, a in enumerate(season):
        if season[i] == season[i-1] or season[i] == season[i+1]:
            return True
   return False

result = check_list(bad_list)

if result == True:
    print "Valid list"
else:
    print "Invalid list"

3 个回答

1

对于更一般的情况,比如“比较前面的元素和后面的元素”,我会使用 itertools.teeitertools.izip,也许可以把这种模式整理成一个工具函数。

另外,你循环里的逻辑有点反了。

# (inside the function)
_behind, _current, _ahead = itertools.tee(the_list, 3)
# should error check as well
_current.next()
_ahead.next()
_ahead.next()
for behind, current, ahead in itertools.izip(_behind, _current, _ahead):
    # fixing logic here
    if behind != current and current != ahead:
        return False
return True

或者

return not any(behind != current and current != ahead for behind, current, ahead in itertools.izip(_behind, _current, _ahead))

注意,你需要特别处理长度为1和长度为2的列表。

1

要修正你的代码,可以把 and 换成 or

if list[i] == list[i-1] or list[i] == list[i+1]:

另外,只有在索引 i-1i+1 不超出列表的范围时,才应该进行这些检查。

这个方法虽然不是性能最好的解决方案,但应该可以正常工作。

我不会直接修正你的代码,因为我觉得你应该自己想办法解决这个问题。

4

我会直接使用 itertools.groupby 这个工具:

if all(len(tuple(group)) > 1 for key, group in itertools.groupby(the_list)):
    print "valid"
else:
    print "invalid"

简单来说,"每个元素前面或后面都应该有一个相同的元素" 这个要求可以理解为 "列表必须由至少两个相邻的相同元素组成"。而 groupby 这个函数就是用来把这些相同的元素分成一组的,你只需要检查这些组的长度是否都大于 1 就可以了。

撰写回答