特定序列存储在列表中

时间:2014-06-27 10:20:20

标签: python list python-3.x return

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

[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)

函数返回: 是的 - 如果序列与我的要求相同, 错 - 如果序列相反

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

5 个答案:

答案 0 :(得分:2)

使用双端队列:

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

答案 1 :(得分:1)

对于很长的列表,这可能会很慢,但它实际上是在进行各种可能的起点时进行列表比较。列表所代表的序列。我假设每个角色可能不止一个,所以你不能直接进入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的双端空格'回答。)

答案 2 :(得分:1)

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

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

答案 3 :(得分:0)

如果有效你的意思是亚线性(即:你不想逐个搜索每个元素),一个好的技巧就是执行{{3} }。

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

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

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

答案 4 :(得分:0)

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

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