2

Suppose that I have the following dictionary:

d = {'q' : 2,
     'b': 22,
     'c': 19,
     'e': 3,
     'd': 9}

What I want to do is to iteratively remove the smallest values (with their keys) from the dictionary. For instance, if I want to remove 2 smallest values, I expect to obtain the following as remaining dictionary:

d = {'b': 22,
     'c': 19,
     'd': 9}

Note that the ordering matters for me in this case. That is, the items in the original dictionary should NOT be reordered after processing.

I tried the below code, but it does not work for an example where dict's length is 19, and I need to remove 18 least values (w/ their associated keys).

def remaining(dict, smallest_n):
    remaining = dict
    s = {}
    for i in range(smallest_n-1):
        m = min(remaining.values())
        for k, v in remaining.items():
            if v != m:
                s[k] = v
        remaining = s.copy()
        s.clear()

    return remaining

For the case I mentioned above, when the smallest_n (which is the number of minimum elements that should be removed) equals to 18, and the input dictionary's size is 19, what I obtain as remaining should have size 1 (19-18). However, it doesn't contain anything after the code lines are being executed.

inverted_index
  • 2,329
  • 21
  • 40
  • 3
    if ordering matters, you shouldn't be using a regular dictionary. you should use an [`OrderedDict`](https://docs.python.org/3.5/library/collections.html#collections.OrderedDict) – wpercy Apr 18 '19 at 20:21
  • Agreed. Use an ordered dictionary. – Robert Harvey Apr 18 '19 at 20:21
  • 1
    also worth mentioning that you probably shouldn't be overwriting `remaining` with the value of `d`... – wpercy Apr 18 '19 at 20:22
  • Is your question just "remove the smallest N values?" – Brad Solomon Apr 18 '19 at 20:23
  • @wpercy thanks! by ordering, I mean that I'm not allowed to modify the initial ordering of the main dictionary. Just updated! – inverted_index Apr 18 '19 at 20:26
  • normal dictionaries like you used do not have an ordering. They often appear to be ordered, but that is simply a coincidence and not guaranteed. If you need it guaranteed, you use an OrderedDict – Tom Lubenow Apr 18 '19 at 20:28
  • Yep! "removing the smallest N values without repositioning the items in the dictionary"? Actually, I'm skeptical what the wrong is with my script? @BradSolomon – inverted_index Apr 18 '19 at 20:28
  • 1
    @Tom [Dicts in Python3.7+ are ordered](https://stackoverflow.com/a/39980744/4518341), though not the way OP needs. – wjandrea Apr 18 '19 at 20:33

2 Answers2

3
min_key = min(d.keys(), key=lambda k: d[k])
del d[min_key]

This will delete the entry with the minimum value. Do this in a loop if you want to remove multiple.

as a function:

def remove_n_minimums(d, n):
    for _ in range(n):
        min_key = min(d.keys(), key=lambda k: d[k])
        del d[min_key]
Tom Lubenow
  • 1,109
  • 7
  • 15
1

You could use

def remove(some_dict, smallest_n = 0):
    # nothing to do
    if not smallest_n:
        return some_dict

    keys_tuple = sorted(
        [(v, k) for k,v in some_dict.items()],
        key = lambda x: x[0]
    )
    for x in range(smallest_n):
        key = keys_tuple[x][1]
        del some_dict[key]

    return some_dict

remove(d, 2)
# {'b': 22, 'c': 19, 'd': 9}

We build a list of tuples with the keys and values. The list will be sorted and the keys in question deleted afterwards. The original dict will be changed with this approach.

Jan
  • 42,290
  • 8
  • 54
  • 79