0

I have a list like this [1]:

[['a1', 'b1', 'c1'], ['a1', 'b1', 'c2'], ['a1', 'b1', 'c3'], 
 ['a1', 'b2', 'c1'], ['a1', 'b2', 'c2'], ['a1', 'b2', 'c3'], 
 ['a1', 'b3', 'c1'], ['a1', 'b3', 'c2'], ['a1', 'b3', 'c3'], 
 ['a2', 'b1', 'c1'], ['a2', 'b1', 'c2'], ['a2', 'b1', 'c3'], 
 ['a2', 'b2', 'c1'], ['a2', 'b2', 'c2'], ['a2', 'b2', 'c3'], 
 ['a2', 'b3', 'c1'], ['a2', 'b3', 'c2'], ['a2', 'b3', 'c3'], 
 ['a3', 'b1', 'c1'], ['a3', 'b1', 'c2'], ['a3', 'b1', 'c3'], 
 ['a3', 'b2', 'c1'], ['a3', 'b2', 'c2'], ['a3', 'b2', 'c3'], 
 ['a3', 'b3', 'c1'], ['a3', 'b3', 'c2'], ['a3', 'b3', 'c3']]

And one like this [2]:

[['a1', 'b1'], ['a2', 'b2']]

And I want to remove sublists of [1] which contain ALL elements in EITHER sublist of [2]. In other words, if a sublist of [1] contains 'a1' and 'b1' or 'a2' and 'b2', it should be removed (only for full matches of the strings).

List [1] should look like this:

[['a1', 'b2', 'c1'], ['a1', 'b2', 'c2'], ['a1', 'b2', 'c3'], 
 ['a1', 'b3', 'c1'], ['a1', 'b3', 'c2'], ['a1', 'b3', 'c3'], 
 ['a2', 'b1', 'c1'], ['a2', 'b1', 'c2'], ['a2', 'b1', 'c3'], 
 ['a2', 'b3', 'c1'], ['a2', 'b3', 'c2'], ['a2', 'b3', 'c3'], 
 ['a3', 'b1', 'c1'], ['a3', 'b1', 'c2'], ['a3', 'b1', 'c3'], 
 ['a3', 'b2', 'c1'], ['a3', 'b2', 'c2'], ['a3', 'b2', 'c3'], 
 ['a3', 'b3', 'c1'], ['a3', 'b3', 'c2'], ['a3', 'b3', 'c3']]

I've tried a similar method to this:

https://stackoverflow.com/a/17934810/6278576

However, I can't figure out how to adapt it to remove sublists from a list when several criteria are met.

How can this be done?

James
  • 32,991
  • 4
  • 47
  • 70
Luka Subo
  • 5
  • 2

4 Answers4

1

You can use a function that filters your list for each group of items in your second list.

def filterall(list_in, *filter_iterables):
    out = list_in.copy()
    for it in filter_iterables:
        out = [x for x in out if not all(i in x for i in it)]
    return out

x = [['a1', 'b1', 'c1'], ['a1', 'b1', 'c2'], ['a1', 'b1', 'c3'], 
 ['a1', 'b2', 'c1'], ['a1', 'b2', 'c2'], ['a1', 'b2', 'c3'], 
 ['a1', 'b3', 'c1'], ['a1', 'b3', 'c2'], ['a1', 'b3', 'c3'], 
 ['a2', 'b1', 'c1'], ['a2', 'b1', 'c2'], ['a2', 'b1', 'c3'], 
 ['a2', 'b2', 'c1'], ['a2', 'b2', 'c2'], ['a2', 'b2', 'c3'], 
 ['a2', 'b3', 'c1'], ['a2', 'b3', 'c2'], ['a2', 'b3', 'c3'], 
 ['a3', 'b1', 'c1'], ['a3', 'b1', 'c2'], ['a3', 'b1', 'c3'], 
 ['a3', 'b2', 'c1'], ['a3', 'b2', 'c2'], ['a3', 'b2', 'c3'], 
 ['a3', 'b3', 'c1'], ['a3', 'b3', 'c2'], ['a3', 'b3', 'c3']]

filterall(x, ['a1', 'b1'], ['a2', 'b2'])
# returns:
[['a1', 'b2', 'c1'], ['a1', 'b2', 'c2'], ['a1', 'b2', 'c3'],
 ['a1', 'b3', 'c1'], ['a1', 'b3', 'c2'], ['a1', 'b3', 'c3'],
 ['a2', 'b1', 'c1'], ['a2', 'b1', 'c2'], ['a2', 'b1', 'c3'],
 ['a2', 'b3', 'c1'], ['a2', 'b3', 'c2'], ['a2', 'b3', 'c3'],
 ['a3', 'b1', 'c1'], ['a3', 'b1', 'c2'], ['a3', 'b1', 'c3'],
 ['a3', 'b2', 'c1'], ['a3', 'b2', 'c2'], ['a3', 'b2', 'c3'],
 ['a3', 'b3', 'c1'], ['a3', 'b3', 'c2'], ['a3', 'b3', 'c3']]
James
  • 32,991
  • 4
  • 47
  • 70
0

You can still use list comprehension, and just nest your predicates:

list1 = [['a1', 'b1', 'c1'], ['a1', 'b1', 'c2'], ['a1', 'b1', 'c3'], 
         ['a1', 'b2', 'c1'], ['a1', 'b2', 'c2'], ['a1', 'b2', 'c3'], 
         ['a1', 'b3', 'c1'], ['a1', 'b3', 'c2'], ['a1', 'b3', 'c3'], 
         ['a2', 'b1', 'c1'], ['a2', 'b1', 'c2'], ['a2', 'b1', 'c3'], 
         ['a2', 'b2', 'c1'], ['a2', 'b2', 'c2'], ['a2', 'b2', 'c3'], 
         ['a2', 'b3', 'c1'], ['a2', 'b3', 'c2'], ['a2', 'b3', 'c3'], 
         ['a3', 'b1', 'c1'], ['a3', 'b1', 'c2'], ['a3', 'b1', 'c3'], 
         ['a3', 'b2', 'c1'], ['a3', 'b2', 'c2'], ['a3', 'b2', 'c3'], 
         ['a3', 'b3', 'c1'], ['a3', 'b3', 'c2'], ['a3', 'b3', 'c3']]
list2 = [['a1', 'b1'], ['a2', 'b2']]

print [sublist1 for sublist1 in list1 if not any([all([item2 in sublist1 for item2 in sublist2]) for sublist2 in list2])]

Prints for me:

[['a1', 'b2', 'c1'], ['a1', 'b2', 'c2'], ['a1', 'b2', 'c3'],
 ['a1', 'b3', 'c1'], ['a1', 'b3', 'c2'], ['a1', 'b3', 'c3'], 
 ['a2', 'b1', 'c1'], ['a2', 'b1', 'c2'], ['a2', 'b1', 'c3'], 
 ['a2', 'b3', 'c1'], ['a2', 'b3', 'c2'], ['a2', 'b3', 'c3'], 
 ['a3', 'b1', 'c1'], ['a3', 'b1', 'c2'], ['a3', 'b1', 'c3'], 
 ['a3', 'b2', 'c1'], ['a3', 'b2', 'c2'], ['a3', 'b2', 'c3'], 
 ['a3', 'b3', 'c1'], ['a3', 'b3', 'c2'], ['a3', 'b3', 'c3']]

If you want to run this on larger data (i.e. very long lists), you may want to turn your lists into sets to allow faster intersections.

Sven Zwei
  • 631
  • 7
  • 5
0

filter + lambda + all combinations

l1 = [['a1', 'b1', 'c1'], ['a1', 'b1', 'c2'], ['a1', 'b1', 'c3'], ['a1', 'b2', 'c1'], ['a1', 'b2', 'c2'], ['a1', 'b2', 'c3'], ['a1', 'b3', 'c1'], ['a1', 'b3', 'c2'], ['a1', 'b3', 'c3'], ['a2', 'b1', 'c1'], ['a2', 'b1', 'c2'], ['a2', 'b1', 'c3'], ['a2', 'b2', 'c1'], ['a2', 'b2', 'c2'], ['a2', 'b2', 'c3'], ['a2', 'b3', 'c1'], ['a2', 'b3', 'c2'], ['a2', 'b3', 'c3'], ['a3', 'b1', 'c1'], ['a3', 'b1', 'c2'], ['a3', 'b1', 'c3'], ['a3', 'b2', 'c1'], ['a3', 'b2', 'c2'], ['a3', 'b2', 'c3'], ['a3', 'b3', 'c1'], ['a3', 'b3', 'c2'], ['a3', 'b3', 'c3']]
l2 = [['a1', 'b1'], ['a2', 'b2']]
list(filter(lambda x: all(not all(j in x for j in i) for i in l2), l1))

Output:

[['a1', 'b2', 'c1'],
 ['a1', 'b2', 'c2'],
 ['a1', 'b2', 'c3'],
 ['a1', 'b3', 'c1'],
 ['a1', 'b3', 'c2'],
 ['a1', 'b3', 'c3'],
 ['a2', 'b1', 'c1'],
 ['a2', 'b1', 'c2'],
 ['a2', 'b1', 'c3'],
 ['a2', 'b3', 'c1'],
 ['a2', 'b3', 'c2'],
 ['a2', 'b3', 'c3'],
 ['a3', 'b1', 'c1'],
 ['a3', 'b1', 'c2'],
 ['a3', 'b1', 'c3'],
 ['a3', 'b2', 'c1'],
 ['a3', 'b2', 'c2'],
 ['a3', 'b2', 'c3'],
 ['a3', 'b3', 'c1'],
 ['a3', 'b3', 'c2'],
 ['a3', 'b3', 'c3']]
Transhuman
  • 3,527
  • 1
  • 9
  • 15
0

Well you can easily do that with for nested loops ...but my guess is that your teacher is trying to make you think how to optimize it.

I would sort each of the arrays. First each one containing strings and then the top level arrays containing arrays.

With that the task becomes m.log(n) where m is the size of the 2nd array and n is the size of the 1st array.

Is this making sense to you ?

Deian
  • 1,237
  • 15
  • 31