Фильтровать список словарей по значению ключа - возвращать ответы в виде списка словарей - PullRequest
4 голосов
/ 11 октября 2019

У меня есть список словарей, которые я хочу отфильтровать.

[{"Slope": -0.562, "Count": 3},
 {"Slope": -0.362, "Count": 6},
 {"Slope": -0.762, "Count": 8},
 {"Slope": -0.562, "Count": 12},
 {"Slope": 2.5, "Count": 34},
 {"Slope": 1.52, "Count": 2},
 {"Slope": .56, "Count": 6}]

Моя цель - получить список из двух словарей. Один с «наибольшим счетом и наклоном POSITVE», а другой - с «наибольшим счетом и отрицательным наклоном».

Мой план состоял в том, чтобы отфильтровать все положительные и отрицательные значения, затем отсортировать каждый список и затем создатьновый список с первой записью каждого.

Сортировка списка не проблема для меня, у меня есть это!

lines_lst.sort(key=lambda i: i['lines_count'])

Но фильтрация не работает, когда я пытаюсь это сделать, так как возвращает словарь.

positive_lines = next(item for item in lines_lst if item["Slope"] > 0)

У кого-нибудь есть решение, которое заканчивается приведенным ниже?

[{"Slope": -0.562, "Count": 12},{"Slope": 2.5, "Count": 34}]

Ответы [ 6 ]

6 голосов
/ 11 октября 2019

Вы хотите максимум и минимум. Используйте их и примените подходящую ключевую функцию - на самом деле, для использования кортежей вам нужно только максимум:

data = [{"Slope": -0.562, "Count": 3},
        {"Slope": -0.362, "Count": 6},
        {"Slope": -0.762, "Count": 8},
        {"Slope": -0.562, "Count": 12},
        {"Slope": 2.5, "Count": 34},
        {"Slope": 1.52, "Count": 2},
        {"Slope": .56, "Count": 6}]

m1 = max(data, key= lambda x: (x["Slope"]>0, x["Count"]))
m2 = max(data, key= lambda x: (x["Slope"]<0, x["Count"]))

result = [m1,m2]

print(result)

Вывод:

[{'Slope': 2.5, 'Count': 34}, {'Slope': -0.562, 'Count': 12}]

Сортировка кортежейпо 1-му значению, затем по второму значению - вы можете создавать кортежи и использовать их в качестве функции максимальной клавиши.

2 голосов
/ 11 октября 2019

Вы можете передать выражение генератора в max():

>>> max((d for d in lines_lst if d["Slope"] > 0), key=lambda d: d["Count"])
{'Slope': 2.5, 'Count': 34}
>>> max((d for d in lines_lst if d["Slope"] < 0), key=lambda d: d["Count"])
{'Slope': -0.562, 'Count': 12}

Конечно, это решение дважды повторяет lines_lst. Если у вас действительно большой ввод, вы можете жадно повторить его один раз, следя за ходом max / min:

import sys

max_pos, max_neg = {"Count": -sys.maxsize}, {"Count": -sys.maxsize}
for d in lines_lst:
    ct = d["Count"]
    if d["Slope"] > 0 and ct > max_pos["Count"]:
        max_pos = d
    elif d["Slope"] < 0 and ct > max_neg["Count"]:
        max_neg = d

Но в Python-стране это, вероятно, полезно только в том случае, если ваш вводдействительно большой и громоздкий.

Обратите внимание, что в обоих этих случаях дальнейшие модификации max_pos / max_neg представляют собой модификации членов lines_lst, поскольку эти члены являются изменяемыми словарями.

1 голос
/ 11 октября 2019

Чтобы указать вашу дополнительную информацию в ответе Патрика, вы можете сделать это, чтобы сначала отсортировать отрицательные / положительные списки:

positives = sorted((v for v in data if v['Slope'] >= 0), key=lambda x: x['Count'])
negatives = sorted((v for v in data if v['Slope'] < 0), key=lambda x: x['Count'])

# positives:
# [{'Slope': 1.52, 'Count': 2}, {'Slope': 0.56, 'Count': 6}, {'Slope': 2.5, 'Count': 34}]

# negatives:
# [{'Slope': -0.562, 'Count': 3}, {'Slope': -0.362, 'Count': 6}, {'Slope': -0.762, 'Count': 8}, {'Slope': -0.562, 'Count': 12}]

Получить максимум на этом этапе просто. Просто найдите последний элемент:

max_pox = positives[-1]     # {'Slope': 2.5, 'Count': 34}
max_neg = negatives[-1]     # {'Slope': -0.562, 'Count': 12}

Или, если хотите, в форме списка:

[x[-1] for x in (negatives, positives)]

# [{'Slope': -0.562, 'Count': 12}, {'Slope': 2.5, 'Count': 34}]
1 голос
/ 11 октября 2019

Создать ключ Count2, который является отрицательным для отрицательных уклонов. Затем отсортируйте по Count2 и возьмите первый и последний элементы.

lines_lst = [{"Slope": -0.562, "Count": 3},
 {"Slope": -0.362, "Count": 6},
 {"Slope": -0.762, "Count": 8},
 {"Slope": -0.562, "Count": 12},
 {"Slope": 2.5, "Count": 34},
 {"Slope": 1.52, "Count": 2},
 {"Slope": .56, "Count": 6}]


for i in range(len(lines_lst)):
    lines_lst[i]['Count2'] = lines_lst[i]['Count']*lines_list[i]['Slope']/abs(lines_list[i]['Slope'])

lines_lst.sort(key=lambda i: i['Count2'])

[lines_lst[0], lines_lst[-1]]

1 голос
/ 11 октября 2019

Вы можете сделать это следующим образом:

inList = [{"Slope": -0.562, "Count": 3},
{"Slope": -0.362, "Count": 6},
{"Slope": -0.762, "Count": 8},
{"Slope": -0.562, "Count": 12},
{"Slope": 2.5, "Count": 34},
{"Slope": 1.52, "Count": 2},
{"Slope": .56, "Count": 6}]

maximum = max(filter(lambda elem: elem['Slope'] > 0, inList), key=lambda e: e['Count'])
minimum = max(filter(lambda elem: elem['Slope'] < 0, inList), key=lambda e: e['Count'])

Это вернет:

{'Slope': 2.5, 'Count': 34}
{'Slope': -0.562, 'Count': 12}
0 голосов
/ 11 октября 2019

Работает ли это?

data = [{"Slope": -0.562, "Count": 3},
{"Slope": -0.362, "Count": 6},
{"Slope": -0.762, "Count": 8},
{"Slope": -0.562, "Count": 12},
{"Slope": 2.5, "Count": 34},
{"Slope": 1.52, "Count": 2},
{"Slope": .56, "Count": 6}]
positive_lines = []
negative_lines = []
for i in range(len(data)):
    if data[i]["Slope"] < 0:
        negative_lines.append(data[i])
    else:
        positive_lines.append(data[i])
max_counts = []
max_counts.append(max(positive_lines, key=lambda x:x['Count']))
max_counts.append(max(negative_lines, key=lambda x:x['Count']))
print(max_counts)

Вывод:

[{'Slope': 2.5, 'Count': 34}, {'Slope': -0.562, 'Count': 12}]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...