kaksi
kaksi

Reputation: 216

Comparing heterogenous lists of lists

Comparing two lists is tough, there are numerous posts on this subject. But what if I have a list of lists? Simplified to extreme:

 members=[['john',1964,'NY'], \
          ['anna',1991,'CA'], \
          ['bert',2001,'AL'], \
          ['eddy',1990,'OH']]

 cash   =[['john',200], \
          ['dirk',200], \
          ['anna',300], \
          ['eddy',150]]

What I need are differences and intersections:

 a     =[['john',1964,'NY'], \
         ['anna',1991,'CA'], \
         ['eddy',1990,'OH']]    #BOTH in members and cash

 b     =[['bert',2001,'AL']]    #in members only

Usually I handle this with a loop, but I feel it is time to switch to a more pythonic way.

The big problem is that I have to fish out the whole (sub)list while comparing just it's first element. The only way I imagine is to make two sets of names, compare these and recreate the lists (of lists) from the sets of differences. Not much better than a loop.

Upvotes: 1

Views: 92

Answers (2)

jpp
jpp

Reputation: 164823

Here is a pandas solution, which avoids having to explicitly define loops yourself. I only recommend this solution if you are looking to perform further manipulations.

import pandas as pd

members = [['john',1964,'NY'],
           ['anna',1991,'CA'],
           ['bert',2001,'AL'],
           ['eddy',1990,'OH']]

cash = [['john',200],
        ['dirk',200],
        ['anna',300],
        ['eddy',150]]

df_members = pd.DataFrame(members, columns=['name', 'year', 'state'])
df_cash = pd.DataFrame(cash, columns=['name', 'value'])

mask = df_members['name'].isin(set(df_cash['name']))

members_common = df_members[mask].values.tolist()
members_membersonly = df_members[~mask].values.tolist()

# members_common
# [['john', 1964, 'NY'], ['anna', 1991, 'CA'], ['eddy', 1990, 'OH']]

# members_membersonly
# [['bert', 2001, 'AL']]

Upvotes: 1

cs95
cs95

Reputation: 403128

Usually I handle this with a loop, but I feel it is time to switch to a more pythonic way.

Nah, I disagree. This is pythonic, depending on who you ask. Here's what you'd need to do -

  1. Generate sets
  2. Find the intersection and difference

  3. Use the keys from step 2 to build a and b

members_set = {m[0] for m in members}
cash_set = {c[0] for c in cash}

inter = members_set & cash_set
diff = members_set - cash_set 

a = [m for m in members if m[0] in inter]
b = [m for m in members if m[0] in diff]

print(a)
[['john', 1964, 'NY'], ['anna', 1991, 'CA'], ['eddy', 1990, 'OH']]

print(b)
[['bert', 2001, 'AL']]

Upvotes: 1

Related Questions