Python find elements in one list that are not in the other
TL;DR:
SOLUTION (1)
import numpy as np
main_list = np.setdiff1d(list_2,list_1)
# yields the elements in `list_2` that are NOT in `list_1`
SOLUTION (2) You want a sorted list
def setdiff_sorted(array1,array2,assume_unique=False):
ans = np.setdiff1d(array1,array2,assume_unique).tolist()
if assume_unique:
return sorted(ans)
return ans
main_list = setdiff_sorted(list_2,list_1)
EXPLANATIONS:
(1) You can use NumPy's setdiff1d
(array1
,array2
,assume_unique
=False
).
assume_unique
asks the user IF the arrays ARE ALREADY UNIQUE.
If False
, then the unique elements are determined first.
If True
, the function will assume that the elements are already unique AND function will skip determining the unique elements.
This yields the unique values in array1
that are not in array2
. assume_unique
is False
by default.
If you are concerned with the unique elements (based on the response of Chinny84), then simply use (where assume_unique=False
=> the default value):
import numpy as np
list_1 = ["a", "b", "c", "d", "e"]
list_2 = ["a", "f", "c", "m"]
main_list = np.setdiff1d(list_2,list_1)
# yields the elements in `list_2` that are NOT in `list_1`
(2)
For those who want answers to be sorted, I've made a custom function:
import numpy as np
def setdiff_sorted(array1,array2,assume_unique=False):
ans = np.setdiff1d(array1,array2,assume_unique).tolist()
if assume_unique:
return sorted(ans)
return ans
To get the answer, run:
main_list = setdiff_sorted(list_2,list_1)
SIDE NOTES:
(a) Solution 2 (custom function setdiff_sorted
) returns a list (compared to an array in solution 1).
(b) If you aren't sure if the elements are unique, just use the default setting of NumPy's setdiff1d
in both solutions A and B. What can be an example of a complication? See note (c).
(c) Things will be different if either of the two lists is not unique.
Say list_2
is not unique: list2 = ["a", "f", "c", "m", "m"]
. Keep list1
as is: list_1 = ["a", "b", "c", "d", "e"]
Setting the default value of assume_unique
yields ["f", "m"]
(in both solutions). HOWEVER, if you set assume_unique=True
, both solutions give ["f", "m", "m"]
. Why? This is because the user ASSUMED that the elements are unique). Hence, IT IS BETTER TO KEEP assume_unique
to its default value. Note that both answers are sorted.
pythonnumpy
Check if one list contains element from the other
If you just need to test basic equality, this can be done with the basic JDK without modifying the input lists in the one line
!Collections.disjoint(list1, list2);
If you need to test a specific property, that's harder. I would recommend, by default,
list1.stream()
.map(Object1::getProperty)
.anyMatch(
list2.stream()
.map(Object2::getProperty)
.collect(toSet())
::contains)
...which collects the distinct values in list2
and tests each value in list1
for presence.
Check if something is (not) in a list in Python
The bug is probably somewhere else in your code, because it should work fine:
>>> 3 not in [2, 3, 4]
False
>>> 3 not in [4, 5, 6]
True
Or with tuples:
>>> (2, 3) not in [(2, 3), (5, 6), (9, 1)]
False
>>> (2, 3) not in [(2, 7), (7, 3), "hi"]
True
Check if list contains element different from something
For the bare boolean check, you can do sth fancy like this, using map
and any
:
for lst in (a, b, c):
print(any(map("_".__ne__, lst)))
# False
# True
# True
Or be a little more explicit:
any(x != "_" for x in lst)
any
has the advantage of short-circuiting (stopping at the first hit) as compared to your suggested set length approach:
len(set(lst)) > 1
If that makes it faster in the real world depends on your data. If most your lists are only underscores and therefore iterated in their entirety, the set conversion (C-optimized) may well be faster.
Using any() and all() to check if a list contains one set of values or another
Generally speaking:
all
and any
are functions that take some iterable and return True
, if
- in the case of
all
, no values in the iterable are falsy; - in the case of
any
, at least one value is truthy.
A value x
is falsy iff bool(x) == False
.
A value x
is truthy iff bool(x) == True
.
Any non-boolean elements in the iterable are perfectly acceptable — bool(x)
maps, or coerces, any x
according to these rules:
0
,0.0
,None
,[]
,()
,[]
,set()
, and other empty collections are mapped toFalse
- all other values are mapped to
True
.
The docstring for bool
uses the terms 'true'/'false' for 'truthy'/'falsy', and True
/False
for the concrete boolean values.
In your specific code samples:
You’ve slightly misunderstood how these functions work. The following does something completely different from what you thought:
if any(foobars) == big_foobar:
...because any(foobars)
would first be evaluated to either True
or False
, and then that boolean value would be compared to big_foobar
, which generally always gives you False
(unless big_foobar
coincidentally happened to be the same boolean value).
Note: the iterable can be a list, but it can also be a generator or a generator expression (≈ lazily evaluated/generated list), or any other iterator.
What you want instead is:
if any(x == big_foobar for x in foobars):
which basically first constructs an iterable that yields a sequence of booleans—for each item in foobars
, it compares the item to the value held by big_foobar
, and (lazily) emits the resulting boolean into the resulting sequence of booleans:
tmp = (x == big_foobar for x in foobars)
then any
walks over all items in tmp
and returns True
as soon as it finds the first truthy element. It's as if you did the following:
In [1]: foobars = ['big', 'small', 'medium', 'nice', 'ugly']
In [2]: big_foobar = 'big'
In [3]: any(['big' == big_foobar, 'small' == big_foobar, 'medium' == big_foobar, 'nice' == big_foobar, 'ugly' == big_foobar])
Out[3]: True
Note: As DSM pointed out, any(x == y for x in xs)
is equivalent to y in xs
but the latter is more readable, quicker to write and runs faster.
Some examples:
In [1]: any(x > 5 for x in range(4))
Out[1]: False
In [2]: all(isinstance(x, int) for x in range(10))
Out[2]: True
In [3]: any(x == 'Erik' for x in ['Erik', 'John', 'Jane', 'Jim'])
Out[3]: True
In [4]: all([True, True, True, False, True])
Out[4]: False
See also: http://docs.python.org/2/library/functions.html#all
How to check if a list contains all the elements of another list INCLUDING duplicates
Repeated calls to list.count
(for the same list) are very inefficient. You can use collections.Counter
and how it implements differences:
from collections import Counter
def contains(l1, l2):
return not (Counter(l2) - Counter(l1))
>>> contains(["A", "A", "A", "b", "b"], ["A", "A", "b", "b"])
True
>>> contains(["a", "a", "b"], ["a", "b"])
True
>>> contains(["a", "b"], ["a", "a", "b"])
False
>>> contains(["a", "a", "b"], ["a", "b", "c"])
False
Check if listt contains any of another list
You could use a nested Any()
for this check which is available on any Enumerable
:
bool hasMatch = myStrings.Any(x => parameters.Any(y => y.source == x));
Faster performing on larger collections would be to project parameters
to source
and then use Intersect
which internally uses a HashSet<T>
so instead of O(n^2) for the first approach (the equivalent of two nested loops) you can do the check in O(n) :
bool hasMatch = parameters.Select(x => x.source)
.Intersect(myStrings)
.Any();
Also as a side comment you should capitalize your class names and property names to conform with the C# style guidelines.
How to check in javascript if a list contains any element?
In javascript there are no lists but arrays, and you can check their length
property
if(serialNumberList.length > 0) {
// Do your stuff
}
Finding elements not in a list
Your code is not doing what I think you think it is doing. The line for item in z:
will iterate through z
, each time making item
equal to one single element of z
. The original item
list is therefore overwritten before you've done anything with it.
I think you want something like this:
item = [0,1,2,3,4,5,6,7,8,9]
for element in item:
if element not in z:
print(element)
But you could easily do this like:
[x for x in item if x not in z]
or (if you don't mind losing duplicates of non-unique elements):
set(item) - set(z)
Related Topics
Configure Multiple Database Entity Framework 6
Multiple Webrequest in Same Session
Encryption Compatible Between Android and C#
How to Display a Loading Control While a Process Is Waiting for Be Finished
Multiple SQL Statements in One Roundtrip Using Dapper.Net
Is Correct to Use Gc.Collect(); Gc.Waitforpendingfinalizers();
C# Winforms Application to Linux
Use Decimal Values as Attribute Params in C#
Returning a String from Pinvoke
Add the Where Clause Dynamically in Entity Framework
Search Xdocument Using Linq Without Knowing the Namespace
Getting @@Identity from Tableadapter
How to Pass Strings from C# to C++ (And from C++ to C#) Using Dllimport
Onchange Event for HTML.Dropdownlist
Entity Framework Initialization Is Slow -- What How to Do to Bootstrap It Faster