3

I have a list below:

tst = [1,3,4,6,8,22,24,25,26,67,68,70,72]

I want to group the elements from above list into separate groups/lists based on the difference between the consecutive elements in the list (differing by 1 or 2).

If the difference between the consecutive elements is more than 4, then the elements should form a separate list.

My expected output from above input is:

[[1, 3, 4, 6, 8], [22, 24, 25, 26], [67, 68, 70, 72]]

I tried the following code which i think is not the perfect approach.

def lsp(litt):
    lia = []
    for i in range(len(litt)-1):
        if len(litt)>=2:
            if litt[i+1]-litt[i] >= 4:
                lia.append(litt[i])

    litti = []
    for i in lia:
        if i in litt:
            litti.append(litt.index(i))
    litti.insert(0,0)

    littil = []
    for i in range(len(litti)-1):
        littil.append([litti[i],litti[i+1]])

    t1 = []
    for i,j in enumerate(littil):
        t2 = []
        if i==0:
            t2.append([j[0], j[1]])
        if i!=0:
            t2.append([j[0]+1,j[1]])
        t1.append(t2)
    t1 = [i for j in t1 for i in j]

    fl = []
    for i,j in t1:
        fl.append(litt[i:j+1])
    fl.append(litt[t1[-1][1]+1:])
    return fl

I want to achieve this using itertools.groupby, but don't know how to do it.

  • Related: [Grouping / clustering numbers in Python](https://stackoverflow.com/a/14783998/190597), and [Grouping a list of integer, with nearest values](https://stackoverflow.com/a/10017017/190597) – unutbu Jan 19 '19 at 18:17
  • 1
    the answer --> https://stackoverflow.com/a/14783980/6817835 – gold_cy Jan 19 '19 at 18:20

2 Answers2

4

I like this way, defining a slicing method and passing a lambda predicate:

def slice_when(predicate, iterable):
  i, x, size = 0, 0, len(iterable)
  while i < size-1:
    if predicate(iterable[i], iterable[i+1]):
      yield iterable[x:i+1]
      x = i + 1
    i += 1
  yield iterable[x:size]

tst = [1,3,4,6,8,22,24,25,26,67,68,70,72]
slices = slice_when(lambda x,y: y - x > 2, tst)
print(list(slices))
#=> [[1, 3, 4, 6, 8], [22, 24, 25, 26], [67, 68, 70, 72]]

Useful in many cases.

iGian
  • 11,023
  • 3
  • 21
  • 36
2

One more solution using a simple for loop:

tst = [1,3,4,6,8,22,24,25,26,67,68,70,72]    # considering this as already sorted. else use tst.sort()

il = []
ol = []
for k, v in enumerate(tst):                  # enumerate is used give index to list element
    if k > 0:                                # to avoid tst[-1] which will get the last element of the list
        if abs(tst[k] - tst[k-1]) < 3:       # check if differnce is less than 3
            if tst[k-1] not in il:           # insert to inner list "il" only if it doesn't already exist
                il.append(tst[k-1])
            if tst[k] not in il:             # insert to inner list "il" only if it doesn't already exist
                il.append(tst[k])
        else:
            ol.append(list(il))              # if difference is greater than 2 then append it to outer list "ol"
            il = []                          # clear the inner list "il"
ol.append(list(il))                          # finaly append the last "il" to "ol" which didnt went in else for our case "[67, 68, 70, 72]"
print (ol)

#Result: [[1, 3, 4, 6, 8], [22, 24, 25, 26], [67, 68, 70, 72]]
Akash Swain
  • 520
  • 3
  • 13