简体   繁体   中英

Find longest consecutive sub array (not sorted)-Python

v=[1,2,3,11,5,8,9,10,11,6,4] in the list above 1,2,3 are consecutive numbers (1st consecutive set). 8,9,10,11 are consecutive numbers (2nd set,largest one). How can I find this 2nd set? This code below gives the consecutive numbers:

for i in range(len(v)-1):
    if v[i+1]==v[i]+1:
        if v[i-1]!=v[i]-1:
             print(v[i])
        print(v[i]+1)

Output:1,2,3,8,9,10,11

I was thinking of using something like below and add the outputs in a new list and then find out max value of the list.I can't think of a logic to combining those 2 ideas.

for i in range(len(v)-1):
    for j in range(i+1,len(v)):
        if v[j]-v[i]  

I looked at this example but I think that solution is different from what I am looking for. Thanks in advance for your time and suggestion.

You can iterate over the list and keep appending the item to the potentially longest consecutive sub-list, and start a new one if the item not consecutive to the last item of the sub-list, and assign the sub-list as the new longest sub-list if it is longer than the current longest sub-list:

candidate = []
longest = []
for i in v:
    if candidate and candidate[-1] != i - 1:
        if len(candidate) > len(longest):
            longest = candidate
        candidate = []
    candidate.append(i)
if len(candidate) > len(longest):
    longest = candidate

longest becomes:

[8, 9, 10, 11]

You're pretty close. Store the current run as a list, update the best list when necessary and clear it whenever you break the run. Care should be taken to include the last grouping if it appears at the very end of the list.

v = [1,2,3,11,5,8,9,10,11,6,4]
best = []
run = []

for i in range(1, len(v) + 1):
    run.append(v[i-1])

    if i == len(v) or v[i-1] + 1 != v[i]:
        if len(best) < len(run):
            best = run

        run = []

print(best)

Output:

[8, 9, 10, 11]

You can use a sliding window shrinking the size and check if all numbers are in ascending order:

from itertools import islice

def window(seq, n=2):
    "Returns a sliding window (of width n) over data from the iterable"
    "   s -> (s0,s1,...s[n-1]), (s1,s2,...,sn), ...                   "
    it = iter(seq)
    result = tuple(islice(it, n))
    if len(result) == n:
        yield result
    for elem in it:
        result = result[1:] + (elem,)
        yield result


def longestConsecutiveSeq(s):
  for seq in (window(s, i) for i in range(len(s)-1, 1, -1)):
    for subseq in seq:
      l = list(subseq)
      if all((y-x) == 1 for (x, y) in zip(l, l[1:])):
        return l

print(longestConsecutiveSeq([1,2,3,11,5,8,9,10,11,6,4]))

Result: [8, 9, 10, 11]

This algorithm will stop on the first encounter of biggest size .

You can use pandas:

import pandas as pd

v=[1,2,3,11,5,8,9,10,11,6,4]

s = pd.Series(v)

sgc = s.groupby(s.diff().ne(1).cumsum()).transform('count')

result = s[sgc == sgc.max()].tolist()

result

Output:

[8, 9, 10, 11]

Details:

Create a pandas series, use diff to calculate the difference from the previous value. Next, use ne to create a boolean series where the difference is not equal to 1, then cumsum this boolean series to create groups, where consective values are all grouped together. Use, groupby with transform to a count of the group size to each record. Lastly, use boolean indexing to only select parts of the series where the count in a group is equal to the max count of all groups. Then convert to array using tolist .

You can use differences between elements and their indices to group elements using the function 'groupby()':

from itertools import groupby

l = [1, 2, 3, 11, 5, 8, 9, 10, 11, 6, 4]

gb = groupby(enumerate(l), lambda x: x[0] - x[1])
max(([i for _, i in g] for _, g in gb), key=len)
# [8, 9, 10, 11]

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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