bgallday
bgallday

Reputation: 43

trying to return value from dict.items() is not working

There is a problem is have to solve here it is

You are given a string of numbers between 0-9. Find the average of these numbers and return it as a floored whole number (ie: no decimal places) written out as a string. Eg:

"zero nine five two" -> "four"

here is my code

from math import floor

 x = ['one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight','nine']


def average_string(s):
    s = s.split(' ')
    dnumber = {k: i for i, k in enumerate(x)}
    converter = [l for n, l in dnumber.items() for i in s if n == i]
    floorN = floor(sum(converter) - len(converter))

    for i,k in dnumber.items(): 
          if k == floorN:
             return i #<--is this the problem?

print(average_string("zero nine five two"))

why is it returning None is there another way compare and return a value from a dict.items()

Upvotes: 2

Views: 1225

Answers (2)

Onyambu
Onyambu

Reputation: 79288

To reduce the number of foo-loops to be used, including sum you can do:

def average_string(s):
    x = ['one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight','nine']
    total = 0
    for i,j in enumerate(x):
        if j in s:
            total += i+1
    return total//len(s.split())

If you include the zero in the list, then your order becomes 0(n) by doing the following:

def average_string(s):
    x = ['zero','one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight','nine']
    total = 0
    count = 0
    for i,j in enumerate(x):
        if j in s:
            total += i
            count += 1
    return total//count

Upvotes: 0

Jean-Fran&#231;ois Fabre
Jean-Fran&#231;ois Fabre

Reputation: 140246

The result should be "four". But your average formula is wrong: you have to sum then divide not subtract.

So when you're looping (what a strange idea?) in the dictionary, you don't find the value, so you reach the end of the function and python returns None in that case.

So fix the formula, then instead of flooring, convert back to index using integer division so everything is kept as integers, and use x to convert to letter-as-string:

def average_string(s):
    s = s.split(' ')
    dnumber = {k:i for i, k in enumerate(x)}
    converter = [l for n, l in dnumber.items() for i in s if n == i]
    floorN = sum(converter) // len(converter)

    return x[floorN-1]

as an aside, you could put the dnumber computation out of the function, since it doesn't depend on the passed parameters (faster if there are many calls), also you don't really use the dictionary as efficiently as it should be. A clear rewrite would be:

x = ['zero', 'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight','nine']
dnumber = {k:i for i, k in enumerate(x)}

def average_string(s):
    converter = [dnumber[w] for w in s.split()]
    floorN = int(sum(converter) / len(converter))
    return x[floorN]

now that I've put zero in the dictionary, I'm able to convert from letter to digit and back, without any loop, to benefit from fast dict/list lookup.

Upvotes: 1

Related Questions