Группируйте последовательные подсписки вместе, если значение равно, а затем извлекайте значения, имеющие атрибут = 'R' - PullRequest
1 голос
/ 04 февраля 2020

Входные данные:

[[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']....]

Это будет огромный список списков с плавающей запятой и строкой, и мне нужно сгруппировать подсписки вместе на основе строкового значения, если оно равно ' Р'. Приведенные выше списки списков были созданы путем преобразования кадров данных в списки (просто для справки).

Таким образом, я должен найти значение с плавающей точкой, где атрибут равен 'R', а затем поместить это значение в подсписок. Мы группируем данные только тогда, когда атрибут значения 'R', содержащий подсписки, является последовательным. В противном случае они должны быть их собственным подсписком.

Выходные данные:

Данные тега 'R' должны быть вместе, только если они находятся рядом друг с другом или это должен быть отдельный подсписок

[[45.0], [10.0], [60.0], [42.4, 76.0]]

Ответы [ 4 ]

0 голосов
/ 04 февраля 2020
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]]

, то есть точно то, что вы после того, как.

0 голосов
/ 04 февраля 2020

Вы можете использовать для l oop:

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']]]

final_list = []
new_list = []

for l in [e for e in input_data]:
    if new_list:
        final_list.append(new_list)
        new_list = []
    for value, tag in l:
        if tag == 'R':
            new_list.append(value)
        elif new_list:
            final_list.append(new_list)
            new_list = []

print(final_list)     

выход:

[[45.0], [10.0], [60.0], [42.4, 76.0]]
0 голосов
/ 04 февраля 2020

Если я правильно понимаю, вы хотите сгруппировать каждый последовательный кортеж во входном массиве с R в качестве второго элемента. Выходные данные должны быть массивом этих групп, так как любая группа значений с последовательными буквами R отображается как выходной массив в массиве массивов. Это должно работать в python:

def group(input_array):
    r = []
    i = 0
    while( i < len(input_array) ):
        if(input_array[i][1] == 'R'):
            # Figure out how many consecutive R's we have then add the sublist to the return array

            group_end_index = i + 1
            if(group_end_index >= len(input_array)):
                # We've reached the end and have a new group that is one element long
                r.append([input_array[i][0]])
                break
            while(1):
                if( input_array[group_end_index][1] != 'R' ):
                    break
                group_end_index += 1

            r.append(list(map(lambda x: x[0], input_array[i:group_end_index])))
            # + 1 because we know the element at group_end_index does not have an 'R'
            i = group_end_index + 1
        else:
            # Not an 'R', ignore.
            i += 1
    return r


if __name__ == '__main__':
    print(group([[1, 'R'], [2, 'R'], [4, 'A'], [4, 'R']]))

Это, кажется, делает то, что вы хотите для списка элементов, где элементы являются кортежами, или списки с двумя элементами.

0 голосов
/ 04 февраля 2020
def group_consecutive( lists, char ) :
    result = []
    # For each list
    for l in lists :
        local_result = []

        # For each element in list
        for n, c in l :
            # Check if char is the same
            if c == char :
                local_result.append(n)
            # Else, if local_result has any  element
            elif local_result :
                result.append( local_result )
                local_result = []

        # FIX: Append last result if not empty
        if local_result :
                result.append( local_result )

    return result


l1 = [[30.0, 'P'], [45.0, 'R'], [50.0, 'D']]
l2 = [[10.0, 'R'], [20.0, 'D'], [60.0, 'R']]
l3 = [[42.4, 'R'], [76.0, 'R'], [52.0, 'D']]

result = group_consecutive( [ l1, l2, l3 ], 'R' )
print( result )

Предыдущий код дает этот вывод:

[[45.0], [10.0], [60.0] [42.4, 76.0]]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...