473,396 Members | 1,894 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,396 software developers and data experts.

help - iter & dict



Dear Python people,

im a newbie to python and here...so hello!

Im trying to iterate through values in a dictionary so i can find the
closest value and then extract the key for that value....what ive done so far:

def pcloop(dictionary, exvalue):
z = dictionary.itervalues()
y = z - exvalue
v = (y*y)**1/2
if v < 0.001:
u = dictionary.get[z]
return u
ive been working off a couple of books and this is the best i can get it in
short time. I was trying to define a function (its my first!) so that i
could apply to several 'dictionary's and 'exvalue's. The best ive been able
to come up with is iterating over the dictionary values, subtracting the
exvalue, squaring then root squaring to render positive and applying an
error (0.001) which is not the ideal solution i want. Is there any easy way
to iterate through dictionary values and return the key for the minimum. Or
can someone tell me where im going wrong with this def & loop.

regards all

Ali
Aug 3 '06 #1
3 2905
ak***@mappi.helsinki.fi wrote:
Im trying to iterate through values in a dictionary so i can find the
closest value and then extract the key for that value....what ive done so far:
[snip]
short time. I was trying to define a function (its my first!) so that i
could apply to several 'dictionary's and 'exvalue's.
[snip]

If you plan on searching a single dictionary for many values, it may be
much faster to convert the dictionary into a sorted list, and use the
bisect module to find the closest value...

something like:

import bisect

class closer_finder:
def __init__(self, dataset):
self.dataset = dataset
flat = [(k,v) for v,k in dataset.iteritems()]
flat.sort()
self.flat = flat

def __getitem__(self, target):
flat = self.flat
index = bisect.bisect_right(flat, (target, ))

#simple cases, smaller than the smaller,
#or larger than the largest
if index == 0:
v,k = flat[0]
return k,v
elif index == len(flat):
v,k = flat[-1]
return k,v

#otherwise see which of the neighbors is closest.
leftval, leftkey = flat[index-1]
rightval, rightkey = flat[index]

leftdiff = abs(leftval - target)
rightdiff = abs(rightval - target)

if leftdiff <= rightdiff:
return leftkey, leftval
else:
return rightkey, rightval

In [158]:sample_data
Out[158]:{'a': 1, 'c': 6, 'b': 3}

In [159]:d=closer_finder(sample_data)

In [160]:d.flat
Out[160]:[(1, 'a'), (3, 'b'), (6, 'c')]

In [161]:d[4]
Out[161]:('b', 3)

--
- Justin

Aug 3 '06 #2
ak***@mappi.helsinki.fi wrote:
Dear Python people,

im a newbie to python and here...so hello!
Hi Ali, and welcome.
Im trying to iterate through values in a dictionary so i can find the
closest value and then extract the key for that value....what ive done so far:

def pcloop(dictionary, exvalue):
z = dictionary.itervalues()
y = z - exvalue
v = (y*y)**1/2
if v < 0.001:
u = dictionary.get[z]
return u
ive been working off a couple of books and this is the best i can get it in
short time. I was trying to define a function (its my first!) so that i
could apply to several 'dictionary's and 'exvalue's. The best ive been able
to come up with is iterating over the dictionary values, subtracting the
exvalue, squaring then root squaring to render positive and applying an
error (0.001) which is not the ideal solution i want. Is there any easy way
to iterate through dictionary values and return the key for the minimum. Or
can someone tell me where im going wrong with this def & loop.

regards all

Ali
You're doing many interesting things wrong here. :-) I'm going to
take them slightly out of order.

First, very ingenious way to get the absolute value of a number, but
there are a few issues with this that you should know about.

For instance, just as multiplication and division take precedence over
addition and subtraction, the "power" operator ** take precedence over
division, so what you're really doing above is

((y*y)**1)/2

rather than

(y*y)**(1/2)

However, the above still wouldn't work correctly because of the way
python handles integer division. 1/2 == 0 in python, try it at the
interactive prompt and you'll see.

So, you'd have to change at least one of the division's operands to
float to get the proper result you desire.

(y*y)**(1./2)

Except that you should actually use the (built in) abs() function,

v = abs(y)

:-)

Next, the itervalues() method of dicts does not return a number, but
rather a "dictionary-valueiterator" object, as you can see from this:

|>d = {}
|>z = d.itervalues()
|>z
<dictionary-valueiterator object at 0xb6f23c00>

In order to get values out of it you need to iterate over it like so:

for z in d.itervalues():
# Do something with z's here...

You could also get both the keys and values at the same time by
iterating like so:

for k, z in d.iteritems():
# Do something with k's and z's here...

(I'll come back to that.)

Now, a little further down in your function, you seem to want to use
the z value with the get() method of the dict to retrieve the key.
This won't work.

First, you're not *calling* the get method (that uses ()'s) you're
*subscripting* it (that uses []'s.) If your code got this far, it
would break here.

|>d = {}
|>d.get
<built-in method get of dict object at 0xb7dd43e4>
|>d.get[23]
Traceback (most recent call last):
File "<stdin>", line 1, in ?
TypeError: unsubscriptable object

So you want to use ()'s, not []'s.

Further, get() works with *keys*, not *values*. If you call it with a
value, it won't work, instead it will return None. Unless, of course,
you *have* a key with the same value as your value, in which case it
will return the value associated with the key, but NOT the key
associated with the value (that you passed to get().)

In fact, there is no easy way to get the key from a dict given a value.
Dicts work the other way around. (You basically have to iterate
through the values *and* keys, one pair at a time, testing each value
as you go. This is very slow, compared to getting the value given a
key.)

value = d[key]

This is extremely fast. It's pretty much the whole point of a
dictionary that this is very fast.

So, when you build the dict that you pass in to your function, you
might want to build it the other way round, i.e. make the keys the
values and the values keys. However, you might not and here's why:

Dicts can only have one key of any given value of key. Look:

|>d = {1: 'a', 1: 'b'}
|>d
{1: 'b'}
|>d = {'a': 1, 'b': 1}
|>d
{'a': 1, 'b': 1}

So, if you're running a mathematical function on a range of input (x's)
and storing the results (y's) as values in a dict, then you *do* want
the x's to be the keys and the y's to be the values.

I'm guessing that's what you're doing, and if so, you're doing it
correctly.

Let me address one last problem in your code above and then I'll show
you a neat way to return the key whose associated value is closest to
some value exvalue.
In this part of your code,
if v < 0.001:
u = dictionary.get[z]
return u
the return statement should be at the same indentation level as the
assignment statement:

if v < 0.001:
u = dictionary.get[z] # <- note, this won't work
return u

or even just

if v < 0.001:
return dictionary.get[z] # <- note, this won't work

The way you have it now, the return statement would execute immediately
after the if statement, regardless of whether v < 0.001 or not. Not
too bad if the very first value was close enough to exvalue. But if it
wasn't, 'u' would not have been defined by the time the return
statement tried to return it, and you would have gotten a NameError.
You probably already know this, and the indentation error was just a
minor typo.
So, given a dict and an exvalue, how to return the key corresponding
to the value that's closest to exvalue?

here goes...
def pcloop(dictionary, exvalue):
'''
Return the key in dictionary whose value is
closest to exvalue.

If dictionary is empty, return None.
'''

# Get a iterator over *both* keys and values.
diter = dictionary.iteritems()

# Get the first (key, value) pair.
try:
u, z = diter.next()

except StopIteration:
# The dictionary was empty!
# You might want to do something else here
return

# Compute the closeness of the first value.
closest = abs(z - exvalue)

# Create a var to store the closest key
result = u

# Iterate through the rest of the dict.
for u, z in diter:

# Compute the closeness.
v = abs(z - exvalue)

# Check if it's closer than the closest.
if v < closest:

# If so, store the new closest.
closest = v

# And store the new closest key.
result = u

return result
I hope that helps. :-)

Python is an amazing language once you get the hang of it. Enjoy.
Peace,
~Simon

Aug 3 '06 #3
Simon Forman wrote:
ak***@mappi.helsinki.fi wrote:
>Dear Python people,

im a newbie to python and here...so hello!

Hi Ali, and welcome.

>Im trying to iterate through values in a dictionary so i can find the
closest value and then extract the key for that value....what ive done so far:

def pcloop(dictionary, exvalue):
z = dictionary.itervalues()
y = z - exvalue
v = (y*y)**1/2
if v < 0.001:
u = dictionary.get[z]
return u
ive been working off a couple of books and this is the best i can get it in
short time. I was trying to define a function (its my first!) so that i
could apply to several 'dictionary's and 'exvalue's. The best ive been able
to come up with is iterating over the dictionary values, subtracting the
exvalue, squaring then root squaring to render positive and applying an
error (0.001) which is not the ideal solution i want. Is there any easy way
to iterate through dictionary values and return the key for the minimum. Or
can someone tell me where im going wrong with this def & loop.

regards all

Ali

You're doing many interesting things wrong here. :-) I'm going to
take them slightly out of order.

First, very ingenious way to get the absolute value of a number, but
there are a few issues with this that you should know about.

For instance, just as multiplication and division take precedence over
addition and subtraction, the "power" operator ** take precedence over
division, so what you're really doing above is

((y*y)**1)/2

rather than

(y*y)**(1/2)

However, the above still wouldn't work correctly because of the way
python handles integer division. 1/2 == 0 in python, try it at the
interactive prompt and you'll see.

So, you'd have to change at least one of the division's operands to
float to get the proper result you desire.

(y*y)**(1./2)

Except that you should actually use the (built in) abs() function,

v = abs(y)

:-)

Next, the itervalues() method of dicts does not return a number, but
rather a "dictionary-valueiterator" object, as you can see from this:

|>d = {}
|>z = d.itervalues()
|>z
<dictionary-valueiterator object at 0xb6f23c00>

In order to get values out of it you need to iterate over it like so:

for z in d.itervalues():
# Do something with z's here...

You could also get both the keys and values at the same time by
iterating like so:

for k, z in d.iteritems():
# Do something with k's and z's here...

(I'll come back to that.)

Now, a little further down in your function, you seem to want to use
the z value with the get() method of the dict to retrieve the key.
This won't work.

First, you're not *calling* the get method (that uses ()'s) you're
*subscripting* it (that uses []'s.) If your code got this far, it
would break here.

|

In fact, there is no easy way to get the key from a dict given a value.
Dicts work the other way around. (You basically have to iterate
through the values *and* keys, one pair at a time, testing each value
as you go. This is very slow, compared to getting the value given a
key.)

value = d[key]

This is extremely fast. It's pretty much the whole point of a
dictionary that this is very fast.

So, when you build the dict that you pass in to your function, you
might want to build it the other way round, i.e. make the keys the
values and the values keys. However, you might not and here's why:

Dicts can only have one key of any given value of key. Look:

|>d = {1: 'a', 1: 'b'}
|>d
{1: 'b'}
|>d = {'a': 1, 'b': 1}
|>d
{'a': 1, 'b': 1}

So, if you're running a mathematical function on a range of input (x's)
and storing the results (y's) as values in a dict, then you *do* want
the x's to be the keys and the y's to be the values.

I'm guessing that's what you're doing, and if so, you're doing it
correctly.

[this is what i want but am not sure its correct]
So, given a dict and an exvalue, how to return the key corresponding
to the value that's closest to exvalue?

here goes...


thanks simon for this, it seems a little easier to understand for me but
i still get the error when i run the script:

#here is a sample dictionary from the 1000 key:values normally in it.
they are all non zero and values to 15 decimal places

CDSitdict = {32.030822391220937: "'1.3679999999999874'",
29.150765445901769: "'2.2079999999999727'", 27.930109636681877:
"'2.744999999999993'", 28.590095427450688: "'2.4359999999999813'",
27.595161357952588: "'2.9219999999999997'", 29.961761413410386:
"'1.9229999999999674'", 36.311798000222424: "'0.66300000000000048'",
34.358611987430052: "'0.93300000000000072'", 41.199188199569292:
"'0.20400000000000013'", 29.560651138651014: "'2.057999999999967'"}
#i have tried to format the numerical key into the dictionary to give a
string using %s but it didnt work so eventually i used
#
#itera = "\'" + `DSit` + "\'"
#CDSitdict[Cpcmax] = itera
#
#i am now wondering if i have been trying to iterate through the key
value pairs, does the numerical part im trying to iterate over have to
be the value #side or can it be any side?

#here is a sample exvalue Cpcb = 33.94
**************************************************
def pcloop(dictionary, exvalue):
'''
Return the key in dictionary whose value is
closest to exvalue.

If dictionary is empty, return None.
'''

# Get a iterator over *both* keys and values.
diter = dictionary.iteritems()

# Get the first (key, value) pair.
try:
u, z = diter.next()

except StopIteration:
# The dictionary was empty!
# You might want to do something else here
return

# Compute the closeness of the first value.
closest = abs(z - exvalue)

# Create a var to store the closest key
result = u

# Iterate through the rest of the dict.
for u, z in diter:

# Compute the closeness.
v = abs(z - exvalue)

# Check if it's closer than the closest.
if v < closest:

# If so, store the new closest.
closest = v

# And store the new closest key.
result = u

return result

Cpcb = input("\n\nPlease enter the carbon percentage value obtained from
the microanalysis. If none, enter 0: ")
print"\n\nCellulose Carbon Percentage is " + `Cpca` + "\n\nMaximum
potential monomer carbon weight is " + `Cwmax` + "\n\nMaximum potential
carbon percentage is " + `Cpcmax` + "\n\nPercentage difference between
Cellulose and Maximum is " + `Cdiff` + "\n\n"
exvalue = Cpcb
dictionary = CDSitdict
CDS = pcloop(dictionary, exvalue)

****************************************
error is:
Traceback (most recent call last):
File "elementalDS.py", line 184, in ?
CDS = pcloop(dictionary, exvalue)
File "elementalDS.py", line 158, in pcloop
closest = abs(z - exvalue)
TypeError: unsupported operand type(s) for -: 'str' and 'float'
:(
ali

--
Dr. Alistair King
Research Chemist,
Laboratory of Organic Chemistry,
Department of Chemistry,
Faculty of Science
P.O. Box 55 (A.I. Virtasen aukio 1)
FIN-00014 University of Helsinki
Tel. +358 9 191 50429, Mobile +358 (0)50 5279446
Fax +358 9 191 50366

Aug 4 '06 #4

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

10
by: Des Small | last post by:
Lately I have found myself using a pattern to make new dictionaries quite often, by which I mean twice: def invert(d): nd = {} ).append(key) for k, v in d] return nd def count(l): d = {}
20
by: Pierre Fortin | last post by:
Hi! "Python Essential Reference" - 2nd Ed, on P. 47 states that a string format can include "*" for a field width (no restrictions noted); yet... >>> "%*d" % (6,2) # works as expected ' ...
45
by: Joh | last post by:
hello, i'm trying to understand how i could build following consecutive sets from a root one using generator : l = would like to produce : , , , ,
125
by: Raymond Hettinger | last post by:
I would like to get everyone's thoughts on two new dictionary methods: def count(self, value, qty=1): try: self += qty except KeyError: self = qty def appendlist(self, key, *values): try:
21
by: Steven Bethard | last post by:
Jack Diederich wrote: > > itertools to iter transition, huh? I slipped that one in, I mentioned > it to Raymond at PyCon and he didn't flinch. It would be nice not to > have to sprinkle 'import...
4
by: Tuure Laurinolli | last post by:
Someone pasted the original version of the following code snippet on #python today. I started investigating why the new-style class didn't work as expected, and found that at least some instances...
1
by: Rex_chaos | last post by:
Hi all, I have designed an iterator and a container like these template <class T> class Iter { ... public: Iter( Container& c, int c ) :cont(c), current(c) T& operator*() {return cont;}
7
by: Kamran | last post by:
Hi, Having problem with boost and stuck. I have the following: std::map <std::string, boost::anybinaryHeader; and somewere else I write: ---------------...
2
by: theronnightstar | last post by:
I am writing an anagram program for my fiance. Figured it would be an excellent task to learn from. The way it is supposed to work is it reads in a word list from a file into a temporary...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.