问题描述
我有一个唯一值列表 lst
,其中可能包含(整数)和整数列表。给定一些 y
,我想找出 x
是否出现在 y
中的 lst
之前。我有以下功能可以完成这项工作,但它的可读性不是很强。有没有更好的方法来写这个,最好使用 next()
方法?我不知道如何在列表推导式中包含嵌套的 if 语句,因此无法真正从那里开始。
lst = [1,2,[3,4],5,[6,7],8]
def x_appears_before_y_in_lst(lst,x,y):
for els in lst:
if isinstance(els,list):
if x in els:
if y not in els:
return True
else:
return False
else:
if y in els:
return False
else:
if els != y:
if els == x:
return True
else:
return False
x_appears_before_y_in_lst(lst,6) (== True)
编辑:忘记包括如果 x
和 y
出现在 lst
的同一个列表中,则函数返回 False,所以
x_appears_before_y_in_lst(lst,3,4) (== False)
解决方法
先展平列表,然后检查是否x in lst[:lst.index(y)]
。或者用简单的语言,从 lst
到 y
取一个切片,然后检查 x
是否在该切片中。如果不是,则 x
在 y
之后。
您可以使用 itertools.chain
因此您不会使用任何嵌套列表,因为您似乎所做的只是检查 x
是否在 y
之前
from itertools import chain
def x_appears_before_y_in_lst(lst,x,y):
for els in chain(lst):
if els == x:
return True
if els == y:
return False
return False
,
我稍微简化了您的代码,它的工作方式始终相同,但更短:)
lst = [1,2,[3,4],5,[6,7],8]
def x_appears_before_y_in_lst(lst,y):
for els in lst:
if isinstance(els,list):
if x in els and y not in els:
return True
elif els != y and els == x:
return True
return False
x_appears_before_y_in_lst(lst,6) (== True)
,
您可以尝试使用递归函数将列表展平,然后比较每个值的索引。
def flattenList(lst):
# Create an empty list
flattened = []
# Iterate through the list
for item in lst:
# If the item is also a list,recursivly flatten it
if isinstance(item,list):
flattened = flattened + flattenList(item)
# If the item is not a list,append it to the flattened list
else:
flattened.append(item)
return flattened
def x_appears_before_y_in_lst(lst,y):
# Find the index of each
xIndes = list.index(x)
yIndex = lst.index(y)
return x < y
,
您应该先展平列表。之后检测相对位置变得微不足道。为了将嵌入的列表项视为相同的索引,扁平版本可以是值位置的字典,以便子列表中的项可以分配相同的位置。
def isBefore(lst,y):
flat = {v:i for i,lv in enumerate(lst) for v in (lv if isinstance(lv,list) else [lv])}
return x in flat and y in flat and flat[x]<flat[y]
输出:
lst = [1,8]
print(isBefore(lst,6)) # True
print(isBefore(lst,6,7)) # False
print(isBefore(lst,4,7)) # True
print(isBefore(lst,3)) # False
print(isBefore(lst,3,4)) # False
或者,您可以将所有项目转换为列表并使用 min()/max() 来确定 x 和 y 的位置
def isBefore(lst,y):
lists = [ v if isinstance(v,list) else [v] for v in lst]
px = min((i for i,lv in enumerate(lists,1) if x in lv),default=0)
py = max((i for i,1) if y in lv),default=0)
return px>0 and py>0 and px < py
这将涵盖列表中有多个 x 和/或 y 实例的情况,如果 x 的至少一个实例在 y 的实例之前,则返回 True。
lst = [1,8,1]
print(isBefore(lst,7,8)) # True
print(isBefore(lst,1)) # True
print(isBefore(lst,2)) # False
,
如果您不想使列表变平,可以尝试此操作。
V