在python中列出模式查找器?

时间:2019-12-19 13:46:35

标签: python python-3.x list function dictionary

我正在尝试制作python列表模式查找器。我的第一个想法是获取列表中的第一个值,然后查找下一个相同值的值。那就是潜在的模式序列长度,然后我将检查在可能的模式序列长度范围内,从第一个数字到第二个数字是否等于第二个数字之后的值。

例如:

如果我有此列表

[1, 2, 6, 1, 2, 6, 1, 2, 6, 7, 8, 7, 8]

然后它将采用第一个数字1并采用列表中第二个1的索引减去第一个数字的索引。因此,3 - 0 = 3就是模式长度。然后它将检查是否list[:3] == list[3:3 + pattern length]。依此类推,直到模式不匹配为止。最终结果将是[[3, [1, 2, 6]], [2, [7, 8]]]。最好将字典作为输出,但是如果两个模式相同,则dictionaru将不起作用,因为它不能具有两个相同的键。

我发现这种方法不是很有效,或者我的函数没有完全成功,所以我想知道是否有人可以帮助我解决另一个模式查找器函数的想法,或者是否有一个python模块来解决这个问题。

我在网上找到了这个:https://regex101.com/r/Vdhjld/1,它确实满足我的要求,但是我的实际列表非常大,使用该列表需要花费很多时间。关于我应该做什么的任何想法?

如果描述不清楚,请发表评论

1 个答案:

答案 0 :(得分:1)

我正在写这作为答案,因为要详细说明。
我认为您应该首先明确自己的要求,这不是一个琐碎的问题,尤其是如果清单很长,则有多种解决方案。

一些可能出现问题的示例:

让我们首先列出以下列表:

[1, 2, 1, 2, 1, 2, 3, 1, 2, 1, 2, 3, 1, 2, 1]

在此列表中找到模式有多种(所有正确的)解决方案:

  1. [3, [1, 2], 1, [3], 2, [1, 2] , 1, [3, 1, 2, 1]
  2. [1, [1, 2], 2, [1, 2, 1, 2, 3], 1, [1, 2, 1]]
  3. [1, [1], 2, [2, 1], 2, [2, 3, 1, 2, 1]]
  4. [2, [1, 2], 2, [1, 2, 3, 1, 2], 1 [1]]

其中哪个应该是您问题的“正确”答案?即使我们说,子序列最长的那个,我们仍然有三个不同的解决方案。列表长度只有15,并且只有三个不同的数字,列表越大,列表中可能出现的解决方案就越不同。我唯一想到的解决方案是,通过搜索最长的公共序列,从列表中删除它,然后重复进行直到列表为空,任意选择一个解决方案。但是,这可能会给您的排序带来麻烦,并且可能会很慢。如果有人有更好的方法,我很高兴听到。

它卡在了我的头上,我无事可做,所以我只是尝试了一下,它没有排序,您必须这样做,但是它提取出最长的常用模式。但是它是递归的,所以我不知道它是否适用于您的长列表,但是它可以为您提供解决方法的思路。我不认为这是迄今为止最快的方法,它只是处理它的一种方法。只是将其用作一种想法,并牢记这一点编写您自己的代码。现在是(相当长的)代码:

test = [1, 2, 3, 1, 2, 3, 1, 2, 3, 4, 5, 4, 5, 1, 2, 3, 1, 2, 3, 1, 2, 3, 4, 5, 4]
test_1 = [1, 2, 3, 1, 2, 3, 1]
test_2 = [1, 2, 1, 2, 1, 2, 3, 1, 2, 1, 2, 3, 1, 2, 1, 2]
test_3 = [1, 1, 1, 2, 1, 1, 1]

def pattern_finder(mylist, pattern):
    matches = []
    i = 0
    while i < len(mylist):
        if mylist[i] == pattern[0] and mylist[i:i+len(pattern)] == pattern:
            matches.append(i)
            i += len(pattern)
        else:
            i+=1
    return matches

def get_patterns(list_input, p=None):
    if type(list_input[0]) != list:
        list_input = [list_input]
    result = []
    for list_in in list_input:
        if len(set(list_in)) == 1:
            result.append([1,list_in])
            continue
        n = len(list_in)
        if n == 1:
            result.append(list_in[0])
            continue
        p_len = p
        if p == None:
            p_len = int(n/2)
        lhs = 0
        rhs = lhs + p_len
        list_split = list_in
        if p_len <= 1:
            result.append([1, list_in])
            continue
        found = False
        while lhs < n - p_len and not found:
            rhs = lhs + p_len
            while rhs <= n-p_len:
                if list_in[lhs:lhs+p_len] == list_in[rhs:rhs+p_len]:
                    found = True
                    matches = pattern_finder(list_in, list_in[lhs:lhs+p_len])
                    list_split = []

                    for i,m in enumerate(matches):
                        if i == 0 and m != 0:
                            list_split.append(list_in[0:m])
                            continue
                        if i == len(matches)-1:
                            if m+p_len != n:
                                list_split.append(list_in[m+p_len:])
                            continue
                        if m+p_len != matches[i+1]:
                            list_split.append(list_in[m+p_len:matches[i+1]])
                    result.append([len(matches), list_in[lhs:lhs+p_len]])
                    break
                rhs += 1
            lhs += 1
        if list_split == []:
            continue
        if not found:
            result += get_patterns(list_split, p_len-1)
        else:
            result += get_patterns(list_split)
    return result

print("Result:", get_patterns(test))