繁体   English   中英

特定序列存储在列表中

[英]Specific sequence stored in a list

我正在寻找一种有效搜索具有特定值序列的列表的方法。 顺序很重要! 例如:

[x,y,z]和[x,z,y]包含相同的值,但它们的顺序不同

然而:

  • [x,y,z],[y,z,x]和[z,x,y]对我来说都是一样的。
  • [x,z,y],[z,y,x]和[x,z,y]也是相同的。

我想bout运行一个脚本来寻找部分连接。 例如,如果我正在寻找[x,y,z]我会看

mylist1 = ['a','b','c']
mylist2 = ['b','a','c']
def is_sequence_same(thelist,somelist):
    if (thelist[0] == somelist[0] and thelist[1] == somelist[1]):
       return True
    if (thelist[1] == somelist[1] and thelist[2] == somelist[2]):
        return True
    if (thelist[0] == somelist[1] and thelist[1] == somelist[0]):
        return False
    if  (thelist[0] == somelist[2] and thelist[1] == somelist[2]):
        return False
    else:
        return None
is_sequence_same(mylist1,mylist2)

函数返回:True - 如果序列与我要求的相同,则为False - 如果序列相反

我目前的职能不完整。 但是,我认为应该有更优雅的方法来解决问题

使用双端队列:

from collections import deque

def is_sequence_same(l1, l2):
    if l1 == l2:
        return True
    if set(l1) != set(l2) or len(l1) != len(l2):
        return False
    d2 = deque(l2)
    for i in range(len(l2)):
        if l1 == list(d2):
            return True
        d2.rotate()
    return False

对于非常长的列表,这可能很慢,但它实际上是在列表比较的同时旋转列表所代表的序列的各种可能的“起始点”。 我假设每个角色可能不止一个,所以你不能直接进入mylist的第一场比赛[0]

mylist = ['a','b','c']
wontmatch = ['b','a','c']
willmatch = ['c','a','b']

def sequence_equal(list1,list2):
    for r in range(0,len(list1)):
        if list1 == list2:
            return True
        # Take the entry from the last index, and put it at the front, 
        # 'rotating' the list by 1
        list1.insert(0,list1.pop())
    return False

print sequence_equal(mylist,willmatch)
print sequence_equal(mylist,wontmatch)

(编辑:这会从Magnus的回答中手动重新创建双端队列。)

由于它是您正在寻找的特定周期,您可以修改两个列表以从相同的元素开始,然后比较它们。 适用于任何列表大小。 假设列表的元素是唯一的。

def is_sequence_same(list_a, list_b):
    if list_a and list_a[0] in list_b:                 # List_a not empty and first element exists in list_b
        first = list_b.index(list_a[0])                # Locate first element of list_a in list_b
    else:
        return False
    return list_a == (list_b[first:] + list_b[:first]) # Slice and compare

例如:

a = [1, 2, 3]
b = [3, 1, 2]
c = [2, 1, 3]

> is_sequence_same(a, b)
> True

> is_sequence_same(b, c)
> False
> 
> is_sequence_same(a, c)
> False

如果有效地意味着亚线性(即:您不想逐个搜索每个元素),一种好的技术是执行数据规范化

如果您的元素有订单,如您的示例中所示,这非常简单:

def normalize_sequence( seq ):
    return tuple(sorted( seq )) #tuple is needed because lists are unhashable

使用此技术,您可以轻松使用字典或集合来执行快速查找:

existing_elements= set( map( normalize_sequence, ([1,4,2],[4,5,7]) ) )
print normalize_sequence( [1,2,4] ) in existing_elements

这比迭代和比较每个元素要快得多,特别是对于较大的列表。

这假定列表保证非空且长度相同:

def is_sequence_same(first, second):
    try:
        i = second.index(first[0])
        if i == -1:
            return False
        for e in first[1:]:
            i += 1
            if i == len(second):
                i = 0
            if e != second[i]:
                return False
        return True
    except ValueError:
        return False

暂无
暂无

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

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