Stellar Streams
Stellar Streams

Reputation: 57

Finding a not exact match in a list of lists

Let's say I have a list of lists like

    new_list=[[1,2,3],
              [9,1,6],
              [7,3,4]]

I'd like to do something like

    n=new_list.index([7,:,4])

and I'd like

n==2

because indeed,

new_list[2]==[7,3,4]

I hope this example makes my point, I want to find if a list of lists contains a certain list without especifying the full list to be found.

Upvotes: 3

Views: 1313

Answers (3)

user2314737
user2314737

Reputation: 29417

One can define a partial "match" function where None matches all and then use next to find the first partial match (similar to what index does, finding only the first match):

pMatch = lambda l1, l2: all([x[0] == x[1] or x[0] == None for x in zip(l1, l2)]) 

# examples of partial matches
pMatch([1, 2, None], [1, 2, 3])                                                                                                                                                             
# True
pMatch([1, 2, 4], [1, 2, 3])                                                                                                                                                                
# False

new_list = [[1, 2, 3], [9, 1, 6], [7, 3, 4]]
l = [7, None, 4]

next(i for i in range(len(new_list)) if pMatch(l, new_list[i]))    
# 2

In one line:

next(i for i in range(len(new_list)) if all([x[0]==x[1] or x[0]==None for x in zip(l, new_list[i])])) 
# 2

(assuming that all lists have the same length)

Upvotes: 1

dede
dede

Reputation: 726

This function should do it (quick&dirty):

>>> new_list=[[1,2,3],
...           [9,1,6],
...           [7,3,4]]
>>> 
>>> def find(lst, members):
...   for i in range(len(lst)):
...     match=True
...     for j in members:
...       if j not in lst[i]:
...         match=False
...         break
...     if match:
...       return i
...   return None
... 
>>> find(new_list, [2, 3])
0
>>> find(new_list, [3, 1])
0
>>> find(new_list, [2, 4])
>>> find(new_list, [7, 4])
2
>>> find(new_list, [7])
2
>>> find(new_list, [8, 9])

Upvotes: 0

Roland Weber
Roland Weber

Reputation: 3675

Approach this in two steps:

  1. Define a function that compares a list against a partial list. You can use None instead of the colon from your example.

    def matches(pattern, candidate):
      # check that pattern and candidate are lists of same length
      # loop over all indices i:
      #   if pattern[i] is not None, candidate[i] must be equal
    
  2. Then loop over the list of lists, calling the function from 1. on each element, until you find an item that matches or the list ends.

Upvotes: 0

Related Questions