from itertools import groupby
input_data = [
[[30.0, 'P'], [45.0, 'R'], [50.0, 'D']],
[[10.0, 'R'], [20.0, 'D'], [60.0, 'R']],
[[42.4, 'R'], [76.0, 'R'], [52.0, 'D']]]
print (sum([[list(j) for i,j in
groupby([item[0] if item[1] == 'R' else None for item in sublist],lambda x:x is not None) if i]
for sublist in input_data],[]))
Результат:
[[45.0], [10.0], [60.0], [42.4, 76.0]]
Деривация
Если вы думаете о группировании чего-либо, вы должны взглянуть на то, что groupby
может сделать для вы. Для простоты давайте сначала используем только часть вашего более длинного списка, чтобы разобраться:
i = input_data[2]
print ([(key,*lst) for key,lst in groupby(i, lambda x: x[1]=='R')])
и покажем, как groupby
работает для вашего ввода:
[(True, [42.4, 'R'], [76.0, 'R']), (False, [52.0, 'D'])]
, потому что два значения R
находятся в одном сгруппированном списке, а другое значение - в другом. Вас не интересуют эти False
значения, поэтому не включайте их:
print ([list(lst) for key,lst in groupby(i, lambda x: x[1]=='R') if key])
, и это даст вам
[[[42.4, 'R'], [76.0, 'R']]]
Пожалуйста, проверьте результаты для другого подпункта -списки в ваших примерах данных!
Легко не включать значения групповых ключей True
и False
, но у вас все еще есть строки 'R'
(которые, кстати, добавляют еще один уровень скобок). Теперь groupby
может в конечном итоге только решить, включать или не включать элемент в группу. Таким образом, вы не можете переписать его, чтобы «вернуть» только номер для R
элементов. (Кстати, я с радостью исправлю это.)
Но вас не интересуют значения, которые не помечены в любом случае R
; Вам нужно только знать, что может быть какое-то значение , и, если оно есть, это только для разбивки на R
. Вы можете безопасно заменить их на None
, сохраняя значения R
:
>>> print ([item[0] if item[1] == 'R' else None for item in i])
[42.4, 76.0, None]
, что означает, что ранее groupby
больше не должен проверять наличие R
, а not None
:
>>> j = [item[0] if item[1] == 'R' else None for item in i]
>>> print ([list(lst) for key,lst in groupby(j, lambda x: x is not None) if key])
[[42.4, 76.0]]
Это, по запросу, список, содержащий списки непрерывных элементов (здесь только один список, но каждая из ваших других строк ввода будет отличаться). Подожди, мы почти у цели.
Это тестирование было проведено для одного элемента в вашем длинном списке, и поэтому легко перевести l oop поверх оригинала:
for i in input_data:
...
Распечатывать, например, можно с помощью этого l oop. Тем не менее, вы хотите, чтобы список снова. Вы можете использовать append
, конечно, но давайте немного повеселимся и добавим понимание списка вокруг текущего groupby
:
print ([
[list(lst) for key,lst
in groupby([item[0] if item[1] == 'R' else None for item in i],
lambda x: x is not None) if key]
for i in input_data])
Не пугайтесь его длины ! Это наша ранняя groupby
, но вместо переменной i
она содержит само понимание списка в качестве первого аргумента. Внешний слой новый; это только эта стандартная оболочка
[ <em>original list comprehension</em> for i in input_data]
и показывает
[[[45.0]], [[10.0], [60.0]], [[42.4, 76.0]]]
Откуда взялись эти дополнительные скобки? Мы начали с отдельных элементов (мы изменили список [45.0, 'R']
в один элемент 45.0
), сгруппировали их по вхождению, сгруппировали , что по подсписку, и итог - список этих списков. , Вам нужен список всего , а не список списков, поэтому давайте сложим их вместе, сведя список. (Сведение списков - хорошо изученный вопрос , и вы можете выбрать любой метод, но мне больше нравится sum
, потому что он хранит все в одной строке ...)
Только использование приведенного выше результата в качестве входных данных:
print (sum([[[45.0]], [[10.0], [60.0]], [[42.4, 76.0]]],[]))
аккуратно показывает, что внешний слой дополнительных скобок исчез:
[[45.0], [10.0], [60.0], [42.4, 76.0]]
, то есть точно то, что вы после того, как.