LinuxQuestions.org
Latest LQ Deal: Latest LQ Deals
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 08-17-2005, 07:40 AM   #1
DiagonalArg
LQ Newbie
 
Registered: Mar 2004
Posts: 23

Rep: Reputation: 15
Accessing nested dictionaries in Python


Hi. I was wondering if anyone could help me with this problem.

I have a list of integers, i=[i1, i2, ..., in], and a dictionary, d, and I want to write some code that will assign a value, x, to d[i1][i2]...[in], the difficulty is that this code will be run repeatedly with different length i's.

Does anyone know how I can do this?
 
Old 08-17-2005, 08:00 AM   #2
jayemef
Member
 
Registered: Aug 2005
Location: Juniata College, PA
Distribution: Ubuntu, Slackware
Posts: 67

Rep: Reputation: 15
Could you provide some pseudo-code? I'm not sure I follow what you're trying to do, but I'd be glad to help.
 
Old 08-17-2005, 08:16 AM   #3
DiagonalArg
LQ Newbie
 
Registered: Mar 2004
Posts: 23

Original Poster
Rep: Reputation: 15
Ok, so my actual problem involves nested for loops.

Say I have three nested for loops, and do something like
Code:
d={}
for i1 in range(something):
    d[i1]={}
    for i2 in range(something):
        d[i1][i2]={}
        for i3 in range(something):
            d[i1][i2][i3]=x
Now, in my program I want to be able to decide how many nested for loops I have at runtime, so I define the same thing recursively. The problem is that I need some code that generalises all of the above assignments, i.e., d[i1]={}, d[i1][i2]={} and d[i1][i2][i3]=x. In my case I have a list of counters [i1,i2,...,in] and want some way of recovering d[i1][i2]...[in] from this.

I'm sorry if this explanation is a bit confusing - I'm not sure how best to describe the problem!
 
Old 08-17-2005, 08:59 AM   #4
jayemef
Member
 
Registered: Aug 2005
Location: Juniata College, PA
Distribution: Ubuntu, Slackware
Posts: 67

Rep: Reputation: 15
Yeah, sorry, but I still don't follow. It might be better if you explain your desired goal, rather than your intended solution to the goal, as there could be a better way.

Also, just something to take note of, but because dictionaries aren't sequential, you can't create double-subscripted dictionaries like you could lists or tuples. However, you could probably create a dictionary within a dictionary to basically acheieve the same thing, as that is what a multi-dimensional list/tuple is anyway.
 
Old 08-17-2005, 09:42 AM   #5
DiagonalArg
LQ Newbie
 
Registered: Mar 2004
Posts: 23

Original Poster
Rep: Reputation: 15
The output of my program is a multi-dimensional dictionary, but the dimension is only decided at runtime - it could be 2, 3, 4, ... etc. - and I need a generic way to assign a value to this dictionary regardless of the dimension. I.e., if it turns out to be two dimensional then I need something like d[i1][i2]=x, if it's three dimensional I need d[i1][i2][i3]=x, and so on.

Also, I'm not quite sure what you mean about not being able to create double subscripted dictionaries. I would have something like myDict={1:{1:a, 2:b}, 2:{1:c, 2:d}}, in which case I could (I'm pretty sure) assign x in place of, say, c with the statement myDict[2][1]=x.

It probably seems a bit obtuse to be using dictionaries instead of lists, but there is a reason for it which is far to boring to go in to!
 
Old 08-17-2005, 01:28 PM   #6
jayemef
Member
 
Registered: Aug 2005
Location: Juniata College, PA
Distribution: Ubuntu, Slackware
Posts: 67

Rep: Reputation: 15
Interesting, you're right about the multi-subscripted dictionaries. I had no idea that would work. Thanks for the info.
 
Old 08-17-2005, 07:48 PM   #7
carl.waldbieser
Member
 
Registered: Jun 2005
Location: Pennsylvania
Distribution: Kubuntu
Posts: 197

Rep: Reputation: 32
Is this what you want to do?

Code:
DIMS = 3

class MultiDimDict(dict):
	def __init__(self, dimensions):
		dict.__init__(self)
		self.dimension = dimensions - 1
	def __getitem__(self, key):
		if self.dimension == 0:
			return dict.__getitem__(self, key)
		else:
			return self.setdefault(key, MultiDimDict(self.dimension)) 
	def __setitem__(self, key, value):
		if self.dimension == 0:
			dict.__setitem__(self, key, value)
		else:
			raise "Illegal assignment to non-leaf dimension!"

m = MultiDimDict(DIMS)
m['a']['b']['c'] = "dog"
m['x']['y']['z'] = 'cat'

print m['a']['b']['c']
print m

#Demonstrate some errors.
#print m['a']['c']['b']
#m['a']['b'] = 'cow'
 
Old 08-18-2005, 02:00 AM   #8
enemorales
Member
 
Registered: Jul 2004
Location: Santiago, Chile
Distribution: Ubuntu
Posts: 410

Rep: Reputation: 31
That works if all the dimensions are the same. If that is not the case I've a second solution (which I don't like, but probably works): Create a string with the assignment and then use the exec() command.

Code:
def i2s(indexes):
  '''Converts a list of indexes into a "mutldimentional dictionary key string'''
  s = ""
  for i in indexes: s += "["+str(i)+"]"                 # This is not efficient in python!
  return s

.
.
.
indexes = [1,3,4,7,2]                             # This's your list of indexes
s = "mydict"+i2s(indexes)+" =  x"         # Here we create a string s = "mydict[1][3][4][7][2] = x"
exec(s)                                                  # And we execute it!
 
Old 08-18-2005, 05:31 AM   #9
DiagonalArg
LQ Newbie
 
Registered: Mar 2004
Posts: 23

Original Poster
Rep: Reputation: 15
Quote:
Originally posted by enemorales
That works if all the dimensions are the same. If that is not the case I've a second solution (which I don't like, but probably works): Create a string with the assignment and then use the exec() command.

Code:
def i2s(indexes):
  '''Converts a list of indexes into a "mutldimentional dictionary key string'''
  s = ""
  for i in indexes: s += "["+str(i)+"]"                 # This is not efficient in python!
  return s

.
.
.
indexes = [1,3,4,7,2]                             # This's your list of indexes
s = "mydict"+i2s(indexes)+" =  x"         # Here we create a string s = "mydict[1][3][4][7][2] = x"
exec(s)                                                  # And we execute it!
Yes, this is the sort of thing that I need. I was hoping there might be some kind of builtin function or method that would do the job, but I guess there isn't. I guess I may have to come up with a different method altogether because, as you say, this won't be very efficient and I'm going to need to repeat this bit of code a lot of times.
 
Old 08-18-2005, 05:44 AM   #10
enemorales
Member
 
Registered: Jul 2004
Location: Santiago, Chile
Distribution: Ubuntu
Posts: 410

Rep: Reputation: 31
Well, I don't know exactly which problem you are trying to solve, but maybe you can use only one dictionary an "encode" the indexes in the key. Something like

a["1-3-6-3-6"] <---> a[1][3][6][3][6]

This could easily become a mess (to keep consistency), but may lead to another type of solution to your problem...
 
Old 08-18-2005, 05:38 PM   #11
carl.waldbieser
Member
 
Registered: Jun 2005
Location: Pennsylvania
Distribution: Kubuntu
Posts: 197

Rep: Reputation: 32
Quote:
Originally posted by enemorales
That works if all the dimensions are the same
Here's a new one that can have jagged dimensions:
Code:
DIMS = 3

class MultiDimDict(dict):
	def __init__(self, dimensions):
		dict.__init__(self)
		self.dimension = dimensions - 1
	def __getitem__(self, key):
		if self.dimension == 0:
			return dict.__getitem__(self, key)
		else:
			return self.setdefault(key, MultiDimDict(self.dimension)) 
	def __setitem__(self, key, value):
		if self.dimension == 0:
			dict.__setitem__(self, key, value)
		else:
			raise "Illegal assignment to non-leaf dimension!"

class MultiDict(dict):
	def __getitem__(self, key):
		try:
			return dict.__getitem__(self, key)
		except:
			return self.setdefault(key, MultiDict()) 

m = MultiDimDict(DIMS)
m['a']['b']['c'] = "dog"
m['x']['y']['z'] = 'cat'

print m['a']['b']['c']
print m
print

#Demonstrate some errors.
#print m['a']['c']['b']
#m['a']['b'] = 'cow'

m2 = MultiDict()
m2[1][2][3][4] = "four"
m2[1][1] = "two"

print m2[1][1]
print m2[1][2][3][4]
print m2
 
Old 08-18-2005, 05:45 PM   #12
carl.waldbieser
Member
 
Registered: Jun 2005
Location: Pennsylvania
Distribution: Kubuntu
Posts: 197

Rep: Reputation: 32
Quote:
Originally posted by enemorales
Well, I don't know exactly which problem you are trying to solve, but maybe you can use only one dictionary an "encode" the indexes in the key. Something like

a["1-3-6-3-6"] <---> a[1][3][6][3][6]

This could easily become a mess (to keep consistency), but may lead to another type of solution to your problem...
If you want to have a multi-part key, you can add the values to a tuple instead of pasting them in a string:
[CODE]
a[(last_name, first_name)] = ssn
[CODE]
This has the advantage that it is easy to create the key, and it is easy to extract the individual values from the key using tuple unpacking.
 
Old 08-19-2005, 08:46 AM   #13
DiagonalArg
LQ Newbie
 
Registered: Mar 2004
Posts: 23

Original Poster
Rep: Reputation: 15
Quote:
Originally posted by carl.waldbieser
If you want to have a multi-part key, you can add the values to a tuple instead of pasting them in a string:
[CODE]
a[(last_name, first_name)] = ssn
[CODE]
This has the advantage that it is easy to create the key, and it is easy to extract the individual values from the key using tuple unpacking.
Thanks for all the suggestions, I think this could possibly work. I'm going to have a try now and see if I can change my code to use tuple keys.
 
Old 08-20-2005, 08:37 PM   #14
jonaskoelker
Senior Member
 
Registered: Jul 2004
Location: Denmark
Distribution: Ubuntu, Debian
Posts: 1,524

Rep: Reputation: 47
Quote:
Code:
a[(last_name, first_name)] = ssn
You don't need the paranthesis; the commas create the tuple, the paranthesis just does grouping where appropriate.

Code:
a[last_name, first_name] = ssn
.. should work just as fine. Similarly w. numbers

hth --Jonas
 
  


Reply



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
Accessing Linux's Help Textfile from Python Li-chan Programming 4 03-12-2005 10:51 AM
Python function arguments are dictionaries? johnMG Programming 1 07-24-2004 06:29 PM
Passwords and Dictionaries bleistein Linux - Newbie 2 07-29-2003 03:25 PM
Passwords and Dictionaries bleistein Linux - Newbie 0 07-29-2003 12:45 PM
dictionaries alaios Linux - General 1 01-24-2003 07:51 AM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 12:49 AM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration