разобрать подсписки списка в python - PullRequest
1 голос
/ 25 февраля 2020

В python мне нужно проанализировать список, состоящий из подсписков. Если первые элементы некоторых подсписков совпадают, мне нужно выбрать подсписок с наименьшим 4-м элементом; но если 4-е элементы также одинаковы, то мне нужно выбрать подсписок с более высоким 3-м элементом. Например, в следующем списке мне нужно выбрать подсписки 1, 4 и 5.

alignments=[["A","B","10","4"],["A","C","15","8"],["A","E","20","10"],\
            ["D","C","15","3"],\
            ["G","U","1","9"],["G","O","10","9"]]

Я добился этого с помощью приведенного ниже кода, который очень громоздок:

best_alignments=[]
best_al=alignments[0]
k=0
c=0

counter_list=[]
for al in alignments[1:]:
    c+=1
    if best_al[0]==al[0]:
        if best_al[3]==al[3]:
            if best_al[2]<al[2]:
                best_al=al
                counter_list.append(c-1)
            else:
                counter_list.append(c)
        else:
            counter_list.append(c)
    else:
        if k==0:
            best_al=al
            k+=1
        else:
            best_al=al
for index in sorted(counter_list, reverse=True):
    del alignments[index]   
for el in alignments:
    print(el)

I Я уверен, что есть гораздо более простой способ сделать это. Любые предложения приветствуются.

Ответы [ 2 ]

1 голос
/ 25 февраля 2020

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

a = [["A","B","10","4"],["A","C","15","8"],["A","E","20","10"],
     ["D","C","15","3"],
     ["G","U","1","9"],["G","O","10","9"]]

seen    = set()
sortKey = lambda sl: (sl[0],-int(sl[3]),sl[2])
first   = lambda sl: sl[0] not in seen and not seen.add(sl[0])   
result  = [ sl for sl in sorted(a,key=sortKey) if first(sl) ]
print(result)
# [['A', 'E', '20', '10'], ['D', 'C', '15', '3'], ['G', 'U', '1', '9']]

При этом используется ключевой параметр отсортированной функции, чтобы создать порядок сортировки, который объединит 3 поля (в обратном порядке для второго поля сортировки). Затем фильтрует отсортированный список, используя набор, чтобы идентифицировать первое вхождение первого поля подсписка в каждой последовательной группе.

1 голос
/ 25 февраля 2020

Вот метод, который по существу делает два прохода по данным. Сначала он группирует данные по первому элементу. Затем он возвращает максимум, определенный по вашим критериям, наименьший третьего элемента и большую часть четвертого (при условии, что вы имели в виду целочисленное значение строки).

from collections import defaultdict

def foo(alignments):
    grouped = defaultdict(list)
    for al in alignments:
        grouped[al[0]].append(al)
    return [
        max(v, key=lambda al: (-int(al[2]),int(al[3])))
        for v in grouped.values()
    ]

Почти уверен, что это O (N) пространство и время, поэтому не очень неэффективно.

В I python repl:

In [3]: from collections import defaultdict
    ...: def foo(alignments):
    ...:     grouped = defaultdict(list)
    ...:     for al in alignments:
    ...:         grouped[al[0]].append(al)
    ...:     return [
    ...:         max(v, key=lambda al: (-int(al[2]),int(al[3])))
    ...:         for v in grouped.values()
    ...:     ]
    ...:

In [4]: foo([['A', 'B', '10', '4'],
    ...:  ['A', 'C', '15', '8'],
    ...:  ['A', 'E', '20', '10'],
    ...:  ['D', 'C', '15', '3'],
    ...:  ['G', 'U', '1', '9'],
    ...:  ['G', 'O', '10', '9']])
Out[4]: [['A', 'B', '10', '4'], ['D', 'C', '15', '3'], ['G', 'U', '1', '9']]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...