473,698 Members | 2,439 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

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(dictiona ry, exvalue):
z = dictionary.iter values()
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 2919
ak***@mappi.hel sinki.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.iterite ms()]
flat.sort()
self.flat = flat

def __getitem__(sel f, target):
flat = self.flat
index = bisect.bisect_r ight(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_finde r(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.hel sinki.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(dictiona ry, exvalue):
z = dictionary.iter values()
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(dictiona ry, 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.iter items()

# 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.hel sinki.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(dictiona ry, exvalue):
z = dictionary.iter values()
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.03082239122 0937: "'1.36799999999 99874'",
29.150765445901 769: "'2.20799999999 99727'", 27.930109636681 877:
"'2.74499999999 9993'", 28.590095427450 688: "'2.43599999999 99813'",
27.595161357952 588: "'2.92199999999 99997'", 29.961761413410 386:
"'1.92299999999 99674'", 36.311798000222 424: "'0.66300000000 000048'",
34.358611987430 052: "'0.93300000000 000072'", 41.199188199569 292:
"'0.20400000000 000013'", 29.560651138651 014: "'2.05799999999 9967'"}
#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(dictiona ry, 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.iter items()

# 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\nPlea se enter the carbon percentage value obtained from
the microanalysis. If none, enter 0: ")
print"\n\nCellu lose Carbon Percentage is " + `Cpca` + "\n\nMaximu m
potential monomer carbon weight is " + `Cwmax` + "\n\nMaximu m potential
carbon percentage is " + `Cpcmax` + "\n\nPercen tage difference between
Cellulose and Maximum is " + `Cdiff` + "\n\n"
exvalue = Cpcb
dictionary = CDSitdict
CDS = pcloop(dictiona ry, exvalue)

*************** *************** **********
error is:
Traceback (most recent call last):
File "elementalDS.py ", line 184, in ?
CDS = pcloop(dictiona ry, 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
2887
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
3296
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 ' 2' Now, with a mapping....
45
3036
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
7180
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
2167
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 itertools as it' in code. iter could also > become a type wrapper instead of a function, so an iter instance could > be a wrapper that figures out whether to call .next or __getitem__ > depending on it's argument. > for item in...
4
2078
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 of new-style classes apparently don't return true for PyInstance_Check, which causes a problem in PySequence_Check, since it will only do an attribute lookup for instances. Things probably shouldn't be this way. Should I go to python-dev with...
1
583
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
1657
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: --------------- binaryHeader.insert(make_pair("job", 0));
2
1930
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 vector<string>. From that it selects a random word 6 letters or more long. That is the word of the game - the one to make all the anagrams from. After it selects a word, I initialize two more vector<string>'s - unplayed_anagrams and played_anagrams. I want...
0
8683
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main usage, and What is the difference between ONU and Router. Let’s take a closer look ! Part I. Meaning of...
0
8611
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 effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language synchronization. With a Microsoft account, language settings sync across devices. To prevent any complications,...
0
9170
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, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. Here is my compilation command: g++-12 -std=c++20 -Wnarrowing bit_field.cpp Here is the code in...
1
8904
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 Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For most users, this new feature is actually very convenient. If you want to control the update process,...
0
7741
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then launch it, all on its own.... Now, this would greatly impact the work of software developers. The idea...
1
6531
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes instead of User Defined Types (UDT). For example, to manage the data in unbound forms. Adolph will...
0
5867
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert into image. Globals.ThisAddIn.Application.ActiveDocument.Select();...
0
4624
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
1
3052
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system

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.