Solution Sharing

Ok nice. So final code would look like this:

def max_key(my_dictionary):
  for key in my_dictionary:
    max_value = my_dictionary[key]
    max_key = key
    break
  for key in my_dictionary:
    if my_dictionary[key] > max_value:
      max_value = my_dictionary[key]
      max_key = key
  return max_key
1 Like

I’m not sure if you could really call it collaborating, but it was nice figuring out an alternate solution with you!

1 Like

Right on! It may look clunky but it works with a minimum of code patterns, and does not use any built-ins. This model of code may seldom be used in production but it is infinitely important in developing our thinking. Well done.

1 Like

Hi Everyone, I would like to share with you the way that I chose to solve it. (I saw a lot of methods to solve it until I finished my own, you rock guys :metal:)

def max_key(my_dictionary):
  max = 0
  for key in my_dictionary.keys():
      if my_dictionary[key] > max:
        max = my_dictionary[key]
        output = key    
  return output
# Uncomment these function calls to test your  function:
print(max_key({1:100, 2:1, 3:4, 4:10}))
#print 1
print(max_key({"a":100, "b":10, "c":1000}))
#"c"
1 Like

A sort of compilation of different approaches:

def max_key(my_dictionary):
  maxK, maxV = list(my_dictionary.items())[0]
  for k in my_dictionary:
    if my_dictionary[k] > maxV:
      maxV = my_dictionary[k]
      maxK = k
  return maxK

# for time efficiency, check https://stackoverflow.com/a/14624923
def max_key2(my_dictionary):
  return list(my_dictionary.keys())[list(my_dictionary.values()).index(max(my_dictionary.values()))]

def max_key3(my_dictionary):
  for k in my_dictionary:
    if my_dictionary[k] == max(my_dictionary.values()):
      return k

def max_key4(my_dictionary):
  return max(my_dictionary, key=my_dictionary.get)

How could we compare the efficiency of each approach against a large dataset?

I saw something called profile.run() mentioned in this post from Stack Overflow, but could not really figure out the docs with my current knowledge/vocab nor could I implement it on my terminal…

This is not my area but it never hurts to examine things and see what we spot. The first and last are both linear with a constant of 2 (for the two iterations) so O(2N). The second one looks to have a constant of 4 given there are four iterations, but still linear.

The third one would be the least efficient owing that it is quadratic (nested iteration). It could be cured by caching the max() before the loop. It never changes. Then it would be linear with a constant of 2.

Owing that we could very likely conclude that the source code for max() is highly optimized. The fourth one would be a best bet and it’s doubtful we as learners or even seasoned programmers will ever top that for this language. I suspect the source code is written in some flavor or C.

The thing I like about the first example is it is closest to a naive implementation It still uses built-ins, though. list() and dict.items(). The fully naive form will use only linear iteration.

>>> def max_key(d):
	k, v = (None, float("-inf"))
	for h in d:
		if d[h] > v:
			k, v = (h, d[h])
	return k

>>> max_key({"a":100, "b":10, "c":1000})
'c'
>>> 

The only difference is that it uses negative infinity as the minimum instead of a value from the dictionary.

def max_key(my_dictionary):
  for key, value in my_dictionary.items():
    if value == max(my_dictionary.values()):
      return key

Not sure if it could fulfil all the conditions.

Here was my solution :slightly_smiling_face:

def max_key(my_dictionary):
  i = -9999999
  for value in my_dictionary.values():
    if value > i:
      i = value
  for key, value in my_dictionary.items():
    if value == i:
      return key

Really cool to see some of these more concise answers! I’m impressed.
Also - if anyone knows a shorter hand way to get a really low integer than literally typing out -9999999, let me know!

If you check through some of the previous answers you’ll find some neat ways of achieving your goal. Perhaps a small integer isn’t what you really need though, you’re just interested in finding the maximum form a set of values, why not start with one of them?

1 Like

This was mine :slight_smile:

def max_key(my_dictionary):
  biggest_val = max(my_dictionary.values())
  for key in my_dictionary.keys():
     if my_dictionary[key] == biggest_val:
       return key

Are you referring to the use of max() ? I did become aware of this through reading some of the solutions, but chose not to implement it. I really want to see the best that can be done with just the methods that have been taught on the course up until this point

1 Like

I was actually referring to obtaining a decent starting value to test against. A few points above cover the use of float("-inf") for a negative number but others propose starting with a value from the dictionary which I think might be the better choice.

Working with what you’ve learnt isn’t a bad shout. I’d hazard a guess the original intention was to solve this with a loop to practice working with loops and dictionaries. Worth knowing max for the future but practising the topics covered should probably be the priority.

1 Like

Can anyone explain to me how “float(”-inf")" works?

I’m doing the Data Science path, but I don’t remember coming across this during one of the modules.

We rarely need to consider infinity in programming situations, but in calculus it is one of the common limits, as is negative infinity.

float('-inf')

represents the float value of the smallest number on the number line. There is no number less than it.

1 Like

thanks! much appreciated.

1 Like
largest_value = float('-inf')
largest_key = ''
def max_key(my_dictionary):
  for k,v in my_dictionary.items():
    if v>largest_value:
      largest_value = v
      largest_key = k
  return largest_key`Preformatted text`

For the above code, I got the following error:

File “script.py”, line 6, in max_key
if v>largest_value:
UnboundLocalError: local variable ‘largest_value’ referenced before assignment

I have declared the variables prior to the function. So, being global variables, shouldn’t they be accessible within the function as well? or do I have to declare them locally, i.e. within the function? Why does the output say that the variables haven’t been declared?

Globals can be accessed for read, but not for write, hence the UnboundLocalError. Suggest move both of those variables to just inside the function, above the loop.

By read and not write, do you mean that the globals can be used as parameters within a function, but you can’t make any changes to them?

First off, globals need to be minimized, but those that we cannot shuffle away into a function should be read only for good reason. If one function can change a global then others can too. It can make collaboration a real challenge on a large code base.

Parameters are inputs, and as local variables they are reassignable, though we should have good reason to reassign them. Inputs are given with the expectation they will be useful in producing a return value.

For best practice keep your variables local and return something to the caller, rather than overwrite globals. Let the caller do that.


Segue

There’s a Games of Chance challenge that warrants comparison. Everyone is so fixated on each game spelling out the outcome, rather than letting each function do what it is supposed to do, return either a positive value, or a negative one. That’s it. Every function has the exact same return.

money is a global. Let all transactions with this variable also be global in scope. Why piss around with stuff inside individual functions when it has to happen for all of them, anyway? Sort out the scope for this challenge and the rest is child’s play.

from random import choice

def coin_toss():
    return choice(['Heads', 'Tails'])

def win(func, guess):
    return guess.title() == func()
>>> win(coin_toss, 'heads')
False
>>> win(coin_toss, 'heads')
True
>>> win(coin_toss, 'heads')
False
>>> 

>>> money = 100
>>> bet = 10
>>> money += win(coin_toss, 'heads') and bet or -bet
>>> money
90
>>> 

See how easy it is to deal with a global in its own scope?

This is the way I was thinking about solving the challenge: using the sorted() feature.