比较列表(列表)中两个元素的位置

Comparing the positions of two elements in a list (of lists)

我有一个唯一值列表 lst,其中可能包含(整数)列表和整数。给定一些 y,我想知道 x 是否出现在 lst 中的 y 之前。我有以下功能可以完成这项工作,但可读性不是很好。有没有更好的写法,最好使用 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, 2, 6) (== True)

编辑:忘记包括如果 xy 都出现在 lst 的同一个列表中,函数 returns 为假,所以

x_appears_before_y_in_lst(lst, 3, 4) (== False)

首先将列表展平,然后检查是否x in lst[:lst.index(y)]。或者用简单的语言,从 lsty 取一片,然后检查 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, x, 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, 2, 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, x, y):
    
    # Find the index of each
    xIndes = list.index(x)
    yIndex = lst.index(y)
    
    return x < y

您应该先将列表展平。之后检测相对位置变得微不足道。为了将嵌入式列表项视为相同的索引,扁平化版本可以是值位置的字典,以便子列表中的项目可以分配相同的位置。

def isBefore(lst,x,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,2,[3,4],5,[6,7],8]
print(isBefore(lst,2,6)) # True
print(isBefore(lst,6,7)) # False
print(isBefore(lst,4,7)) # True
print(isBefore(lst,6,3)) # False
print(isBefore(lst,3,4)) # False    

或者,您可以将所有项目转换为列表并使用 min()/max() 来确定 x 和 y 的位置

def isBefore(lst,x,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,lv in enumerate(lists,1) if y in lv),default=0)
    return px>0 and py>0 and px < py

这将涵盖以下情况:列表中有多个 x and/or y 实例,并且 return 如果至少有一个 x 实例在 y 实例之前,则为真。

lst = [1,2,8,[3,4],5,[6,7],8,1]

print(isBefore(lst,7,8)) # True
print(isBefore(lst,8,1)) # True
print(isBefore(lst,8,2)) # False

如果你不想扁平化列表,你可以试试这个。

lst = [1,2,[3,4],5,[6,7],8]

def x_before_y(lst, x, y):
    for v in lst:
        if isinstance(v,list):
            if x in v or y in v:
                return x in v and y not in v
        elif v == x or v == y:
            return v == x
    return False

print(x_before_y(lst, 2, 6)) # True
print(x_before_y(lst, 3, 4)) # False
print(x_before_y(lst, 5, 4)) # False