简体   繁体   English

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

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

I have a list of unique values lst that may have lists (of integers) and integers in it.我有一个唯一值列表lst ,其中可能包含(整数)列表和整数。 Given some y , I want to find if x appears before y in lst or not.给定一些y ,我想知道x是否出现在lst中的y之前。 I have the following function that does the job but it's not very readable.我有以下 function 可以完成这项工作,但它的可读性不是很高。 Is there a better way to write this, preferably using the next() method?有没有更好的方法来写这个,最好使用next()方法? I don't know how to include nested if-statements inside a list comprehension, so can't really proceed from there.我不知道如何在列表理解中包含嵌套的 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)

Edit: Forgot to include that if both x and y appear in the same list in lst , the function returns False, so编辑:忘记包括如果xy都出现在lst的同一个列表中,则 function 返回 False,所以

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

Flatten the list first, then check if x in lst[:lst.index(y)] .首先展平列表,然后检查x in lst[:lst.index(y)]是否。 Or in plain language, take a slice of the lst up to y , and check if x is in that slice.或者用简单的语言,取lsty的切片,并检查x是否在该切片中。 If it isn't, then x comes after y .如果不是,则xy之后。

You could use itertools.chain So you're not working with any nested lists as all you seem to be doing is checking if x comes before 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

I simplified your code a bit, the way it works is always the same, but its shorter:)我稍微简化了您的代码,它的工作方式始终相同,但更短:)

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)

You could try flattening the list with a recursive function and then comparing the indexes of each value.您可以尝试使用递归 function 展平列表,然后比较每个值的索引。

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

You should flatten the list first.您应该首先展平列表。 After that detecting the relative positions becomes trivial.之后检测相对位置变得微不足道。 In order to consider embedded list items as the same index, the flattened version could be a dictionary of value positions so that items in a sub-list can be assigned the same position.为了将嵌入的列表项视为相同的索引,展平版本可以是值位置的字典,以便可以为子列表中的项分配相同的 position。

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]

output: output:

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    

Alternatively, you can convert all the items into lists and use min()/max() to determine the positions of x and y或者,您可以将所有项目转换为列表并使用 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

This will cover cases where there are multiple instances of x and/or y in the list and return True if at least one instance of x is before an instance of y.这将涵盖列表中有多个 x 和/或 y 实例的情况,如果至少一个 x 实例在 y 实例之前,则返回 True。

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

You may try this if you don't want to flatten the list.如果您不想展平列表,您可以试试这个。

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

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

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