Merging two lists of data (Pythonic way)

S

SMB

I have two lists of data like the following:

LIST1
[[5L, 1L, 1L, 'Personal Information'], [14L, 2L, 1L, '']]

LIST2
[{'code': 5L, 'name': 'First Name', 'value': [''], 'label': 'First Name',
'width': 0L, 'separator': ',', 'height': 0L, 'type': 2L, 'order': 1L},
{'code': 14L, 'name': 'Last Name', 'value': [''], 'label': 'Last Name',
'width': 0L, 'separator': ',', 'height': 0L, 'type': 2L, 'order': 2L},
{'code': 16L, 'name': 'Job Title', 'value': [], 'label': 'Job Title',
'width': 40L, 'separator': '', 'height': 0L, 'type': 2L, 'order': 3L}]

The important comparison values here are list[0] for each list in LIST1 and
dictionary["code"] for each dictionary in LIST2.

What I am doing is looking for a pythonic way to parse the LIST2 "code"
values and make appropriate changes to to each dictionary if the "code"
value is the first element of a list in LIST1.

The final result may look like this given that the change is adding a new
key/value of "VERIFIED"/1 for the matches.
LIST3
[{'VERIFIED':1,'code': 5L, 'name': 'First Name', 'value': [''], 'label':
'First Name', 'width': 0L, 'separator': ',', 'height': 0L, 'type': 2L,
'order': 1L}, {'VERIFIED':1,'code': 14L, 'name': 'Last Name', 'value': [''],
'label': 'Last Name', 'width': 0L, 'separator': ',', 'height': 0L, 'type':
2L, 'order': 2L}, {'code': 16L, 'name': 'Job Title', 'value': [], 'label':
'Job Title', 'width': 40L, 'separator': '', 'height': 0L, 'type': 2L,
'order': 3L}]

I know I could do this with two for loops, but am looking for a better
solution maybe involving list comprehension.

Any pointers are appreciated.
Thanks
 
J

Jonathan Gardner

codes = map(lambda x: x[0], list1)
for d in list2:
if d['code'] in codes:
d['VERIFIED'] = 1

Is this what you were looking for?
 
S

SMB

Jonathan Gardner said:
codes = map(lambda x: x[0], list1)
for d in list2:
if d['code'] in codes:
d['VERIFIED'] = 1

Is this what you were looking for?

That is exactly what I was looking for. I will have to take a look at map.

Thank you very much
 
S

SMB

Jonathan Gardner said:
codes = map(lambda x: x[0], list1)
for d in list2:
if d['code'] in codes:
d['VERIFIED'] = 1

Is this what you were looking for?

Actually, this is not exactly what I was looking for. I failed to realize
what map did, in this case using the labmda x: x[0] on each item of the list
returning a list of the key numbers. The problem is that the changes made
to my dictionary (in my example dictionary["VERIFIED"]=1) needs to be based
on the other values in each list in LIST1.

In my example LIST1 was defined as
[[5L, 1L, 1L, 'Personal Information'], [14L, 2L, 1L, '']]

So, the dictionary changes would be involving mylist[1:] for each mylist in
LIST1 based on the comparison to mylist[0]...

Thank again
 
D

Dave Hansen

Jonathan Gardner said:
codes = map(lambda x: x[0], list1)
for d in list2:
if d['code'] in codes:
d['VERIFIED'] = 1

Is this what you were looking for?

That is exactly what I was looking for. I will have to take a look at map.

You might also look at list comprehensions. Replacing the first line
in the above with

codes = [x[0] for x in list1]

should yield the same result.

Regards,
-=Dave
 
G

Georg Brandl

Dave said:
Jonathan Gardner said:
codes = map(lambda x: x[0], list1)
for d in list2:
if d['code'] in codes:
d['VERIFIED'] = 1

Is this what you were looking for?

That is exactly what I was looking for. I will have to take a look at map.

You might also look at list comprehensions. Replacing the first line
in the above with

codes = [x[0] for x in list1]

should yield the same result.

Even another way:

import operator
codes = map(operator.itemgetter(0), list1)

Georg
 
P

Paul Rubin

SMB said:
What I am doing is looking for a pythonic way to parse the LIST2 "code"
values and make appropriate changes to to each dictionary if the "code"
value is the first element of a list in LIST1.

The final result may look like this given that the change is adding a new
key/value of "VERIFIED"/1 for the matches.

Untested:

from sets import Set
vvals = Set(a[0] for a in LIST1) # get all the List1 first elt. values
for d in LIST2:
if d['code'] in vvals:
d['VERIFIED'] = 1
I know I could do this with two for loops, but am looking for a better
solution maybe involving list comprehension.

I think if list1 is potentially long, the main thing is to avoid n**2
running time, which means use a set or dict to do the lookups, like
above.
 
G

Gerard Flanagan

Dave said:
Jonathan Gardner said:
codes = map(lambda x: x[0], list1)
for d in list2:
if d['code'] in codes:
d['VERIFIED'] = 1

Is this what you were looking for?

That is exactly what I was looking for. I will have to take a look at map.

You might also look at list comprehensions. Replacing the first line
in the above with

codes = [x[0] for x in list1]

should yield the same result.

Regards,
-=Dave


What about :

A = [ a[0] for a in LIST1 ]
for d in [ d for d in LIST2 if d['code'] in A ]:
d['VERIFIED'] = 1

?

Gerard
 
L

Lonnie Princehouse

You might consider writing two classes to represent the values in list1
and list2. It might be more Pythonic than sloshing around all of those
lists and dictionaries.

But as it is, it looks like you want to find matching pairs of lists
and dictionaries from list1 and list2, respectively:

# index dictionaries from LIST2 by 'code' element.
# (assumption: no two dicts have the same "code" value)
lookup_table = dict( [(d['code'], d) for list in LIST2] )

# iterate over LIST1, matching list1 elements with corresponding list2
elements
pairs = [( L, lookup_table[L[0]]) for L in LIST1 if L[0] in
lookup_table]

# make whatever kind of modifications you want
for list_item, dictionary_item in pairs:
dictionary_item['VERIFIED'] = list_item[2] # or something




And- If you're using Python 2.4, you can get more efficient memory
usage out of this by using generator expressions instead of list
comprehensions.
 
S

Steven D'Aprano

I know I could do this with two for loops, but am looking for a better
solution maybe involving list comprehension.

What's wrong with for loops? Why do you think they are unPythonic?
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,763
Messages
2,569,562
Members
45,038
Latest member
OrderProperKetocapsules

Latest Threads

Top