Перечислить список, отсортированный по двум полям в Python - PullRequest
0 голосов
/ 08 марта 2019

У меня есть массив такого типа:
поле 4 - это среднее значение 1,2,3, а поле 5 - минимум 1,2,3.

[['name0', 24, 19, 25, 22.67, 19],
 ['name1', 25, 19, 25, 23.0, 19],
 ['name2', 25, 19, 25, 23.0, 19],
 ['name3', 24, 22, 23, 23.0, 22],
 ['name4', 27, 19, 25, 23.67, 19],
 ['name5', 27, 19, 25, 23.67, 19],
 ['name6', 28, 19, 26, 24.33, 19],
 ['name7', 28, 19, 26, 24.33, 19],
 ['name8', 28, 19, 26, 24.33, 19],
 ['name9', 26, 22, 27, 25.0, 22],
 ['name10', 27, 23, 25, 25.0, 23],
 ['name11', 30, 19, 27, 25.33, 19],
 ['name12', 24, 31, 28, 27.67, 24],
 ['name13', 28, 27, 28, 27.67, 27],
 ['name14', 27, 29, 27, 27.67, 27],
 ['name15', 29, 26, 29, 28.0, 26],
 ['name16', 29, 26, 30, 28.33, 26],
 ['name17', 30, 31, 26, 29.0, 26],
 ['name18', 33, 27, 30, 30.0, 27],
 ['name19', 29, 31, 30, 30.0, 29],
 ['name20', 30, 36, 31, 32.33, 30],
 ['name21', 36, 30, 32, 32.67, 30],
 ['name22', 38, 33, 36, 35.67, 33],
 ['name23', 30, 27, 99, 52.0, 27],
 ['name24', 99, 27, 32, 52.67, 27],
 ['name25', 37, 99, 36, 57.33, 36]]

Который был отсортирован по полю 4, а затем по полю 5.
Я хотел бы перечислить этот список, создавая своего рода «рейтинг» или «подиум».

enumerate () не работает, потому что, как вы можете видеть, некоторые поля связаны с полями 4 и 5, поэтому их «ранг» должен быть одинаковым.
Например, первые значения должны выглядеть следующим образом:

[['1', 'name0', 24, 19, 25, 22.67, 19],
 ['2', 'name1', 25, 19, 25, 23.0, 19],
 ['2', 'name2', 25, 19, 25, 23.0, 19],
 ['3', 'name3', 24, 22, 23, 23.0, 22],
 ['4', 'name4', 27, 19, 25, 23.67, 19],
 ...]

Не могу придумать, как правильно подойти к этому. Спасибо за помощь.

Ответы [ 4 ]

1 голос
/ 08 марта 2019

Предполагая, что список отсортирован, вы можете сгруппировать подсписки по их 4-му и 5-му элементам, используя ... с точным именем groupby и itemgetter. Используйте enumerate на итераторе, возвращаемом groupby:

from itertools import groupby
from operator import itemgetter

# data = [['name0', ...
[ [str(i+1)] + l for i, (k, g) in enumerate(groupby(data, key=itemgetter(4, 5))) for l in g ]

Выход:

[
    ['1', 'name0', 24, 19, 25, 22.67, 19],
    ['2', 'name1', 25, 19, 25, 23.0, 19],
    ['2', 'name2', 25, 19, 25, 23.0, 19],
    ['3', 'name3', 24, 22, 23, 23.0, 22],
    ['4', 'name4', 27, 19, 25, 23.67, 19],
    ['4', 'name5', 27, 19, 25, 23.67, 19],
    ['5', 'name6', 28, 19, 26, 24.33, 19],
    ['5', 'name7', 28, 19, 26, 24.33, 19],
    ['5', 'name8', 28, 19, 26, 24.33, 19],
    ['6', 'name9', 26, 22, 27, 25.0, 22],
    ['7', 'name10', 27, 23, 25, 25.0, 23],
    ['8', 'name11', 30, 19, 27, 25.33, 19],
    ['9', 'name12', 24, 31, 28, 27.67, 24],
    ['10', 'name13', 28, 27, 28, 27.67, 27],
    ['10', 'name14', 27, 29, 27, 27.67, 27],
    ['11', 'name15', 29, 26, 29, 28.0, 26],
    ['12', 'name16', 29, 26, 30, 28.33, 26],
    ['13', 'name17', 30, 31, 26, 29.0, 26],
    ['14', 'name18', 33, 27, 30, 30.0, 27],
    ['15', 'name19', 29, 31, 30, 30.0, 29],
    ['16', 'name20', 30, 36, 31, 32.33, 30],
    ['17', 'name21', 36, 30, 32, 32.67, 30],
    ['18', 'name22', 38, 33, 36, 35.67, 33],
    ['19', 'name23', 30, 27, 99, 52.0, 27],
    ['20', 'name24', 99, 27, 32, 52.67, 27],
    ['21', 'name25', 37, 99, 36, 57.33, 36]
]
0 голосов
/ 08 марта 2019

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

for i, ((*_, prev_mean, prev_min), (*_, mean, _min)) in enumerate(zip([(None, None)] + l, l)):
    l[i].insert(0, str(l[i - 1][0] if mean == prev_mean and _min == prev_min else i + 1))

Если ваш список списков хранится как переменная l, l становится:

[['1', 'name0', 24, 19, 25, 22.67, 19],
 ['2', 'name1', 25, 19, 25, 23.0, 19],
 ['2', 'name2', 25, 19, 25, 23.0, 19],
 ['4', 'name3', 24, 22, 23, 23.0, 22],
 ['5', 'name4', 27, 19, 25, 23.67, 19],
 ['5', 'name5', 27, 19, 25, 23.67, 19],
 ['7', 'name6', 28, 19, 26, 24.33, 19],
 ['7', 'name7', 28, 19, 26, 24.33, 19],
 ['7', 'name8', 28, 19, 26, 24.33, 19],
 ['10', 'name9', 26, 22, 27, 25.0, 22],
 ['11', 'name10', 27, 23, 25, 25.0, 23],
 ['12', 'name11', 30, 19, 27, 25.33, 19],
 ['13', 'name12', 24, 31, 28, 27.67, 24],
 ['14', 'name13', 28, 27, 28, 27.67, 27],
 ['14', 'name14', 27, 29, 27, 27.67, 27],
 ['16', 'name15', 29, 26, 29, 28.0, 26],
 ['17', 'name16', 29, 26, 30, 28.33, 26],
 ['18', 'name17', 30, 31, 26, 29.0, 26],
 ['19', 'name18', 33, 27, 30, 30.0, 27],
 ['20', 'name19', 29, 31, 30, 30.0, 29],
 ['21', 'name20', 30, 36, 31, 32.33, 30],
 ['22', 'name21', 36, 30, 32, 32.67, 30],
 ['23', 'name22', 38, 33, 36, 35.67, 33],
 ['24', 'name23', 30, 27, 99, 52.0, 27],
 ['25', 'name24', 99, 27, 32, 52.67, 27],
 ['26', 'name25', 37, 99, 36, 57.33, 36]]
0 голосов
/ 08 марта 2019

Использование Pandas и dense rank:

import pandas as pd

df = pd.DataFrame(data = [['name0', 24, 19, 25, 22.67, 19],
 ['name1', 25, 19, 25, 23.0, 19],
 ['name2', 25, 19, 25, 23.0, 19],
 ['name3', 24, 22, 23, 23.0, 22],
 ['name4', 27, 19, 25, 23.67, 19],
 ['name5', 27, 19, 25, 23.67, 19],
 ['name6', 28, 19, 26, 24.33, 19],
 ['name7', 28, 19, 26, 24.33, 19],
 ['name8', 28, 19, 26, 24.33, 19],
 ['name9', 26, 22, 27, 25.0, 22],
 ['name10', 27, 23, 25, 25.0, 23],
 ['name11', 30, 19, 27, 25.33, 19],
 ['name12', 24, 31, 28, 27.67, 24],
 ['name13', 28, 27, 28, 27.67, 27],
 ['name14', 27, 29, 27, 27.67, 27],
 ['name15', 29, 26, 29, 28.0, 26],
 ['name16', 29, 26, 30, 28.33, 26],
 ['name17', 30, 31, 26, 29.0, 26],
 ['name18', 33, 27, 30, 30.0, 27],
 ['name19', 29, 31, 30, 30.0, 29],
 ['name20', 30, 36, 31, 32.33, 30],
 ['name21', 36, 30, 32, 32.67, 30],
 ['name22', 38, 33, 36, 35.67, 33],
 ['name23', 30, 27, 99, 52.0, 27],
 ['name24', 99, 27, 32, 52.67, 27],
 ['name25', 37, 99, 36, 57.33, 36]], columns= ['1', '2', '3', '4', '5', '6'])

df["rank"] = df['5'].rank(method = "dense")
df

>
    1   2   3   4   5   6   rank
0   name0   24  19  25  22.67   19  1.0
1   name1   25  19  25  23.00   19  2.0
2   name2   25  19  25  23.00   19  2.0
3   name3   24  22  23  23.00   22  2.0
4   name4   27  19  25  23.67   19  3.0
5   name5   27  19  25  23.67   19  3.0
6   name6   28  19  26  24.33   19  4.0
7   name7   28  19  26  24.33   19  4.0
8   name8   28  19  26  24.33   19  4.0
9   name9   26  22  27  25.00   22  5.0
10  name10  27  23  25  25.00   23  5.0
11  name11  30  19  27  25.33   19  6.0
12  name12  24  31  28  27.67   24  7.0
13  name13  28  27  28  27.67   27  7.0
14  name14  27  29  27  27.67   27  7.0
15  name15  29  26  29  28.00   26  8.0
16  name16  29  26  30  28.33   26  9.0
17  name17  30  31  26  29.00   26  10.0
18  name18  33  27  30  30.00   27  11.0
19  name19  29  31  30  30.00   29  11.0
20  name20  30  36  31  32.33   30  12.0
21  name21  36  30  32  32.67   30  13.0
22  name22  38  33  36  35.67   33  14.0
23  name23  30  27  99  52.00   27  15.0
24  name24  99  27  32  52.67   27  16.0
25  name25  37  99  36  57.33   36  17.0

Если вы хотите списки списков -

df = df.set_index('rank').reset_index()
df.values.tolist()
0 голосов
/ 08 марта 2019

Начните с i = 1, итерируйте их и назначьте ранг, увеличивая его i += 1, только если следующая строка отличается.

...