2016-08-03 41 views
1

У меня есть список, содержащий случайное число int. Я хотел бы перебрать этот список, и если число и последовательное число находятся в пределах одного числового шага друг друга, я хотел бы объединить их в подсписку.Объединить смежное число в списке в python

Например:

input = [1,2,4,6,7,8,10,11] 
output = [[1,2],[4],[6,7,8],[10,11]] 

В списке ввода всегда будет содержать положительные Интс отсортированных в порядке возрастания. Я пробовал код с here.

initerator = iter(inputList) 
outputList = [c + next(initerator, "") for c in initerator] 

Хотя я могу Concat каждые две записи в списке, я не могу добавить подходящий if в списке понимания.

Python версии = 3,4

+3

Однострочный: '[[x для i, x в grp] для _, grp в itertools.groupby (перечисление (inputList), лямбда x: x [1] - x [0])]'. –

+0

спасибо, это хорошо выглядит ...... и я понимаю работу ... однако, если я добавлю каждую запись буквой, поэтому у меня есть вход = [a1, a2, a4, b6 , c7, c8, c10, d11], я также хотел бы сгруппировать по символу, что привело к [[a1, a2], [a4], [b6], [c7, c8], [c10], [d11]]. ... Я не совсем понимаю методы «groupby» и «enumerate», которые, вероятно, поэтому я не могу получить это ... еще раз спасибо – Eoin

ответ

0

Хороший способ (нашел "расщепление" индексы, а затем нарежьте:.

input = [1,2,4,6,7,8,10,11] 
idx = [0] + [i+1 for i,(x,y) in enumerate(zip(input,input[1:])) if x+1!=y] + [len(input)] 
[ input[u:v] for u,v in zip(idx, idx[1:]) ] 
#output: 
[[1, 2], [4], [6, 7, 8], [10, 11]] 

использованием enumerate() и zip()

0

Если вы не должны иметь один вкладыш , вы можете использовать простую функцию генератора, объединяя элементы до тех пор, пока не нажмете непоследовательный элемент:

def consec(lst): 
    it = iter(lst) 
    prev = next(it) 
    tmp = [prev] 
    for ele in it: 
     if prev + 1 != ele: 
      yield tmp 
      tmp = [ele] 
     else: 
      tmp.append(ele) 
     prev = ele 
    yield tmp 

Выход:

In [2]: lst = [1, 2, 4, 6, 7, 8, 10, 11] 

In [3]: list(consec(lst)) 
Out[3]: [[1, 2], [4], [6, 7, 8], [10, 11]] 
0

Простейшая версия у меня есть без импорта:

def mergeAdjNum(l): 
    r = [[l[0]]] 
    for e in l[1:]: 
     if r[-1][-1] == e - 1: 
      r[-1].append(e) 
     else: 
      r.append([e]) 
    return r 

Около 33% быстрее, чем лайнеры.

Это один обрабатывает префикс символов группировки, упомянутые в комментариях:

def groupPrefStr(l): 
    pattern = re.compile(r'([a-z]+)([0-9]+)') 
    r = [[l[0]]] 
    pp, vv = re.match(pattern, l[0]).groups() 
    vv = int(vv) 
    for e in l[1:]: 
     p,v = re.match(pattern, e).groups() 
     v = int(v) 
     if p == pp and v == vv + 1: 
      r[-1].append(e) 
     else: 
      pp, vv = p, v 
      r.append([e]) 
    return r 

Это путь медленнее, чем число только один. Знать точный формат префикса (только один символ?) Может помочь избежать использования модуля re и ускорить его.