[Tutor] looping through and comparing lists of dictionaries
Don Arnold
Don Arnold" <darnold02@sprynet.com
Wed Apr 23 07:01:40 2003
----- Original Message -----
From: "bkd" <bkd@graphnet.com>
To: <tutor@python.org>
Sent: Wednesday, April 23, 2003 2:04 AM
Subject: [Tutor] looping through and comparing lists of dictionaries
> I have two lists of dictionaries. One is freshly downloaded from a telnet
> screenscrape, the other is read from a file that's a snapshot of the last
> screenscrape:
>
> olddata=[{'name':'Betty','hair':'Blonde','role':'Student'},
> {'name':'Veronica','hair':'Brunette','role':'Student'},
> {'name':'Maryann','hair':'Brunette','role':'Castaway'},
> {'name':'Ginger','hair':'Redhead','role':'Castaway'},
> {'name':'Jeanne','hair':'Blond','role':'Genie'},
> {'name':'Serena','hair':'Brunette','role':'Genie'},
> {'name':'Samantha','hair':'Blond','role':'Witch'}]
>
> newdata=[{'name':'Betty','hair':'Redhead','role':'Student'},
> {'name':'Veronica','hair':'Redhead','role':'Student'},
> {'name':'Maryann','hair':'Brunette','role':'Castaway'},
> {'name':'Ginger','hair':'Redhead','role':'Castaway'},
> {'name':'Jeanne','hair':'Blond','role':'Genie'},
> {'name':'Serena','hair':'Brunette','role':'Genie'},
> {'name':'Samantha','hair':'Redhead','role':'Witch'}]
>
> I want to find all the girls who have dyed their hair red since the last
> time I checked. I start by running a loop that pulls all the names of all
> the Redheads into a list:
>
> redheads=[]
> for girl in range(len(newdata)):
> if newdata[girl]['hair']=='Redhead':
> redheads.append(newdata[girl]['name'])
>
> this gives me:
> ['Betty','Veronica','Ginger','Samantha']
> for redheads.
>
> Now, I need to check olddata to see if any of these girls were redheads,
and
> eliminate them from the list.
>
> What I have now is this:
>
> for girl in range(len(redheads)):
> if len(redheads)==0: break
> else:
> for line in range(len(olddata)):
> if len(redheads)==0: break
> elif olddata[line]['name']<>redheads[girl]: pass
> elif olddata[line]['hair']=='Redhead': del redheads[girl]
>
> But this breaks with an 'index out of range' error. The lesson being, do
not
> mess with the list you're indexing over, make a copy and mess with the
copy.
>
> But still, I can't help but think there must be a better way to do this.
Any
> suggestions where I should look first? Learning Python and the online
> documentation seem fairly anemic when it comes to showing how to really
> wield dictionaries with power, and the Python Cookbook seems to assume one
> has a bit more knowledge about the language than the bundled docs
provide...
>
> bkd
>
Why not just check the old hair color before adding to the redheads list?
redheads = []
for newgirl in newdata:
if newgirl['hair'] == 'Redhead':
for oldgirl in olddata:
if oldgirl['name'] == newgirl['name']:
if oldgirl['hair'] != 'Redhead':
print '%s used to be a %s' % (newgirl['name'],
oldgirl['hair'])
redheads.append(newgirl)
break
print redheads
--output--
Betty used to be a Blonde
Veronica used to be a Brunette
Samantha used to be a Blond
[{'hair': 'Redhead', 'role': 'Student', 'name': 'Betty'}, {'hair':
'Redhead', 'role': 'Student', 'name': 'Veronica'}, {'hair': 'Redhead',
'role': 'Witch', 'name': 'Samantha'}]
--end output--
Also, since Python's for statement iterates over a collection, it's often
cleaner to iterate directly over your list/tuple instead of using range( )
and then indexing into it.
HTH,
Don