Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to retrieve minimum unique values from list?

Tags:

python

I have a list of dictionary. I wish to have only one result for each unique api and the result need to show according to priority: 0, 1, 2. May I know how should I work on it?

Data:

[
{'api':'test1', 'result': 0},
{'api':'test2', 'result': 1},
{'api':'test3', 'result': 2},
{'api':'test3', 'result': 0},
{'api':'test3', 'result': 1},
]

Expected output:

[
{'api':'test1', 'result': 0},
{'api':'test2', 'result': 1},
{'api':'test3', 'result': 0},
]
like image 326
UnKnown Avatar asked Dec 31 '20 09:12

UnKnown


People also ask

How do I extract unique values from a list?

In Excel, there are several ways to filter for unique values—or remove duplicate values: To filter for unique values, click Data > Sort & Filter > Advanced. To remove duplicate values, click Data > Data Tools > Remove Duplicates.


3 Answers

Assuming input data you can do classic sql-ish groupby:

from itertools import groupby

# in case your data is sorted already by api skip the below line
data = sorted(data, key=lambda x: x['api'])

res = [
    {'api': g, 'result': min(v, key=lambda x: x['result'])['result']} 
    for g, v in groupby(data, lambda x: x['api'])
]

Outputs:

[{'api': 'test1', 'result': 0}, {'api': 'test2', 'result': 1}, {'api': 'test3', 'result': 0}]
like image 195
Grzegorz Skibinski Avatar answered Oct 27 '22 14:10

Grzegorz Skibinski


You can pass through the list once and preserve the best ones you see for each group. This is time and space efficient.

def get_min_unique(items, id_key, value_key):
  lowest = {}
  for item in items:
    key = item[id_key]
    if key not in lowest or lowest[key][value_key] > item[value_key]:
        lowest[key] = item
  return list(lowest.values())

For example with your own data:

data = [
  {'api':'test1', 'result': 0},
  {'api':'test2', 'result': 1},
  {'api':'test3', 'result': 2},
  {'api':'test3', 'result': 0},
  {'api':'test3', 'result': 1},
]

assert get_min_unique(data, 'api', 'result') == [
  {'api': 'test1', 'result': 0},
  {'api': 'test2', 'result': 1},
  {'api': 'test3', 'result': 0},
]
like image 42
Cireo Avatar answered Oct 27 '22 15:10

Cireo


data = [
    {'api': 'test1', 'result': 0},
    {'api': 'test3', 'result': 2},
    {'api': 'test2', 'result': 1},
    {'api': 'test3', 'result': 1},
    {'api': 'test3', 'result': 0}
]

def find(data):
    step1 = sorted(data, key=lambda k: k['result'])
    print('step1', step1)

    step2 = {}
    for each in step1:
        if each['api'] not in step2:
            step2[each['api']] = each
    print('step2', step2)

    step3 = list(step2.values())
    print('step3', step3)
    print('\n')
    return step3

find(data)

Try this, it will give you

step1 [{'api': 'test1', 'result': 0}, {'api': 'test3', 'result': 0}, {'api': 'test2', 'result': 1}, {'api': 'test3', 'result': 1}, {'api': 'test3', 'result': 2}]
step2 {'test1': {'api': 'test1', 'result': 0}, 'test3': {'api': 'test3', 'result': 0}, 'test2': {'api': 'test2', 'result': 1}}
step3 [{'api': 'test1', 'result': 0}, {'api': 'test3', 'result': 0}, {'api': 'test2', 'result': 1}]

Sort all first, then find first for each "api", and there goes your result.

like image 7
BananZ Avatar answered Oct 27 '22 15:10

BananZ