By Python 101

2019-11-08 14:09:29 8 Comments

I am working on a question that requires to point out the problem in a function that determines whether a dictionary is invertible (for every value appearing in the dictionary, there is only one key that maps to that value) or not. The question is below:

def is_invertible(adict):
    inv_dict = make_inv_dict(adict)
    return adict == inv_dict

def make_inv_dict(adict):
    if len(adict) > 0:
       key, val = adict.popitem()
       adict = make_inv_dict(adict)
       if val not in adict.values():
          adict[key] = val
       return adict
        return {}

Currently, this returns False for {'a': 'b', 'b': 'e', 'c': 'f'} when it is supposed to be True. I am sure that there is an issue in make_inv_dict function; is it simply because adict is not an appropriate variable name in adict = make_inv_dict(adict)? Or is there another reason why the function returns a wrong outcome?


@Kapil 2019-11-08 14:32:51

My Answer:

def is_invertible(dict_var):
    return len(dict_var.values()) == len(set(dict_var.values()))

@kaya3 2019-11-09 21:25:29

No need to convert the set into a list before you do len - it works perfectly well (and faster) to write len(set(...)).

@kaya3 2019-11-08 14:13:42

At least three problems with the function you've given:

  1. The condition adict == inv_dict checks whether the dictionary is its own inverse, not merely that it's invertible.
  2. It uses pop_item to remove a key/value pair from the input dictionary, and then inserts it backwards, so the function operates in-place. By the time it's finished, adict's original contents will be completely destroyed, so the comparison will be meaningless anyway.
  3. The line adict[key] = val inserts the key/value pair in the original order; the inverse order should be adict[val] = key. So this function doesn't do what its name promises, which is to make an inverse dictionary.

It should be noted that if not for the destruction of the dictionary (2.), the mistakes (1.) and (3.) would cancel out, because the outcome of the function is to rebuild the original dictionary but without duplicate values.

I'm guessing some people will find this question if they're looking for a correct way to invert a dictionary, so here is one: this function returns the inverse dictionary if it's possible, or None otherwise.

def invert_dict(d):
    out = dict()
    for k,v in dict.items():
        if v in out:
            return None
        out[v] = k
    return out

Helper function returning a boolean for whether a dictionary is invertible:

def is_invertible(d):
    return invert_dict(d) is not None

Related Questions

Sponsored Content

16 Answered Questions

[SOLVED] How can I add new keys to a dictionary?

39 Answered Questions

[SOLVED] How do I check whether a file exists without exceptions?

42 Answered Questions

[SOLVED] How do I merge two dictionaries in a single expression?

27 Answered Questions

[SOLVED] How do I check if a list is empty?

  • 2008-09-10 06:20:11
  • Ray Vega
  • 2675167 View
  • 3234 Score
  • 27 Answer
  • Tags:   python list

16 Answered Questions

[SOLVED] Check if a given key already exists in a dictionary

  • 2009-10-21 19:05:09
  • Mohan Gulati
  • 3354365 View
  • 2683 Score
  • 16 Answer
  • Tags:   python dictionary

34 Answered Questions

[SOLVED] How do I sort a dictionary by value?

18 Answered Questions

10 Answered Questions

[SOLVED] Iterating over dictionaries using 'for' loops

28 Answered Questions

[SOLVED] What is the best way to iterate over a dictionary?

  • 2008-09-26 18:20:06
  • Jake Stewart
  • 1535431 View
  • 2537 Score
  • 28 Answer
  • Tags:   c# dictionary loops

11 Answered Questions

[SOLVED] How to remove a key from a Python dictionary?

Sponsored Content