【问题标题】:Python finding repeating sequence in list of integers?Python在整数列表中找到重复序列?
【发布时间】:2012-07-08 18:48:31
【问题描述】:

我有一个列表列表,每个列表都有一个重复序列。我正在尝试计算列表中重复整数序列的长度:

list_a = [111,0,3,1,111,0,3,1,111,0,3,1] 

list_b = [67,4,67,4,67,4,67,4,2,9,0]

list_c = [1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,23,18,10]

哪个会返回:

list_a count = 4 (for [111,0,3,1])

list_b count = 2 (for [67,4])

list_c count = 10 (for [1,2,3,4,5,6,7,8,9,0])

欢迎任何建议或提示。我现在正在尝试使用 re.compile 来解决它,但是它不太正确。

【问题讨论】:

  • 是否 100% 确定该列表只包含相同的重复模式?
  • 是的,肯定有重复的模式。它可以是 1 位数到 200 位数的模式。
  • 正则表达式几乎肯定不是您要寻找的,因为您不处理字符串,并且将列表转换为字符串,IMO 会给您带来远远超过 2 个问题。跨度>
  • 我已将这些列表转换为字符串。你认为会发生什么问题?

标签: python list sequence


【解决方案1】:

通过在序列长度的 2 到一半之间进行迭代来猜测序列长度。如果没有发现模式,则默认返回 1。

def guess_seq_len(seq):
    guess = 1
    max_len = len(seq) / 2
    for x in range(2, max_len):
        if seq[0:x] == seq[x:2*x] :
            return x

    return guess

list_a = [111,0,3,1,111,0,3,1,111,0,3,1] 
list_b = [67,4,67,4,67,4,67,4,2,9,0]
list_c = [1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,23,18,10]

print guess_seq_len(list_a)
print guess_seq_len(list_b)
print guess_seq_len(list_c)
print guess_seq_len(range(500))   # test of no repetition

这给出(如预期的那样):

4
2
10
1

根据要求,此替代方案给出了最长的重复序列。因此它将为 list_b 返回 4。唯一的变化是guess = x 而不是return x

def guess_seq_len(seq):
    guess = 1
    max_len = len(seq) / 2
    for x in range(2, max_len):
        if seq[0:x] == seq[x:2*x] :
            guess = x

    return guess

【讨论】:

  • 我的第一条评论是在我放入一个有错误的列表后发表的。这真的很有帮助,您使用范围进行比较非常棒:D 感谢您的帮助!
  • 很确定这是不正确的,至少它不会找到最佳解决方案。假设 0, 1, 0, 1, 0, 1, 0, 1 - 这可以看作是 4x 2 元素或 2x 4 元素的重复序列,我认为它应该找到更长的序列。
  • @Voo 那是我最初拥有的,但它不适合示例。在这种情况下,list_b 的答案将是 4,而不是问题作者指定的 2。
  • 啊,我看到作者的一个例子明确想要更短的序列 - 很奇怪,但你是对的。
  • @tijko 请看上面-guess = 1 的左行是第一个算法设计的提示。 :)
【解决方案2】:

我采用了Maria 更快、更符合 stackoverflow 的答案,并使其首先找到最大的序列:

def guess_seq_len(seq, verbose=False):
    seq_len = 1
    initial_item = seq[0]
    butfirst_items = seq[1:]
    if initial_item in butfirst_items:
        first_match_idx = butfirst_items.index(initial_item)
        if verbose:
            print(f'"{initial_item}" was found at index 0 and index {first_match_idx}')
        max_seq_len = min(len(seq) - first_match_idx, first_match_idx)
        for seq_len in range(max_seq_len, 0, -1):
            if seq[:seq_len] == seq[first_match_idx:first_match_idx+seq_len]:
                if verbose:
                    print(f'A sequence length of {seq_len} was found at index {first_match_idx}')
                break
    
    return seq_len

【讨论】:

    【解决方案3】:

    这对我有用。

    def repeated(L):
        '''Reduce the input list to a list of all repeated integers in the list.'''
        return [item for item in list(set(L)) if L.count(item) > 1]
    
    def print_result(L, name):
        '''Print the output for one list.'''
        output = repeated(L)
        print '%s count = %i (for %s)' % (name, len(output), output)
    
    list_a = [111, 0, 3, 1, 111, 0, 3, 1, 111, 0, 3, 1]
    list_b = [67, 4, 67, 4, 67, 4, 67, 4, 2, 9, 0]
    list_c = [
        1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2,
        3, 4, 5, 6, 7, 8, 9, 0, 23, 18, 10
    ]
    
    print_result(list_a, 'list_a')
    print_result(list_b, 'list_b')
    print_result(list_c, 'list_c')
    

    Python 的set() 函数会将列表转换为集合,这是一种只能包含任何给定值之一的数据类型,很像代数中的集合。我将输入列表转换为一个集合,然后再转换回一个列表,将列表缩减为只有它的唯一值。然后,我测试了这些值中的每一个的原始列表,看它是否多次包含该值。我返回了所有重复项的列表。其余代码仅用于演示目的,以表明它有效。

    编辑:语法突出显示不喜欢我的文档字符串中的撇号。

    【讨论】:

    • 这没有回答问题。
    猜你喜欢
    • 1970-01-01
    • 2012-08-09
    • 1970-01-01
    • 2017-05-17
    • 1970-01-01
    • 2023-02-09
    • 2021-02-24
    • 1970-01-01
    • 2022-01-05
    相关资源
    最近更新 更多