Reputation: 79
lst_a = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
lst_b = [[1, 4, 7], [6, 5, 4], [9, 8, 7]]
My goal is to check all nested lists in lst_a
if the first entry == first entry of any element in lst_b
. If it's not than copy ONLY THAT sublist. In this example he wouldn't copy lst_a[0]
but 1 and 2.
I tried to achieve my goal with list comprehension but it won't work.
zero = [x[0] for x in lst_a]
if zero not in lst_b:
# I don't know what to do here.
Creating a tuple or a dictionary isn't possible because the whole process is in a loop in which every second new data come in and I try to avoid copying duplicates to the list.
EDIT: lst_b
should look like that after the whole process:
lst_b = [[1, 4, 7], [6, 5, 4], [9, 8, 7], [4, 5, 6], [7, 8, 9]]
Upvotes: 1
Views: 76
Reputation: 103844
Another way:
exclude=set(next(zip(*lst_b)))
lst_b+=[sl for sl in lst_a if sl[0] not in exclude]
>>> lst_b
[[1, 4, 7], [6, 5, 4], [9, 8, 7], [4, 5, 6], [7, 8, 9]]
Explanation:
zip(*lst_b)
is a generator of the inverse of the matrix lst_b
, The *
expands the sub lists and this creates a generator that yields [(1, 6, 9), (4, 5, 8), (7, 4, 7)]
in turn.next(zip(*lst_b)
we only need the first element of that inverse: (1,6,9)
set(next(zip(*lst_b)))
only need the uniq elements of that so turn into a set. You get {1, 6, 9}
(order does not matter)[sl for sl in lst_a if sl[0] not in exclude]
filter on that condition.lst_b+=
extend lst_b
with the filtered elements.Profit!
Upvotes: 2
Reputation: 531165
It's a bit of a mouthful, but not too bad:
lst_b.extend(x for x in lst_a if not any(x[0] == y[0] for y in lst_b)
If you want a new list rather than modifying lst_b
in place, then
lst_c = lst_b + [x for x in lst_a if not any(x[0] == y[0] for y in lst_b)]
In either case, we examine each sublist x
in lst_a
. any(x[0] == y[0] for y in lst_b)
is True
if the first element of the sublist is equal to the first element of any sublist in lst_b
. If that's not true, then we'll include x
in our final result.
Using any
allows us to avoid checking against every sublist in lst_b
when finding a single match is sufficient. (There are cases where this could be more efficient than first creating an entire set of first elements, as in @barmar's answer, but on average that approach is probably more efficient.)
Upvotes: 2
Reputation: 780994
Extract all the first elements from lst_b
into a set so you can check membership efficiently. Then use a list comprehension to copy all the sublists in lst_a
that match your criteria.
first_elements = {x[0] for x in lst_b}
result = [x for x in lst_a if x[0] not in first_elements]
Upvotes: 2
Reputation: 8942
There may be more efficient ways of doing this, but this accomplishes the goal.
>>> [a for a in lst_a if a[0] not in [b[0] for b in lst_b]]
[[4, 5, 6], [7, 8, 9]]
Upvotes: 1