Search code examples
pythonindexinglogical-operatorsindices

Find the indices of elements greater than x


Given the following vector,

a = [1, 2, 3, 4, 5, 6, 7, 8, 9]

I need to identify the indices of "a" whose elements are >= than 4, like this:

idx = [3, 4, 5, 6, 7, 8] 

The info in "idx" will be used to delete the elements from another list X (X has the same number of elements that "a"):

del X[idx] #idx is used to delete these elements in X. But so far isn't working.

I heard that numpy might help. Any ideas? Thanks!


Solution

  • OK, I understand what you mean and a Single line of Python will be enough:

    using list comprehension

    [ j for (i,j) in zip(a,x) if i >= 4 ]
    # a will be the list compare to 4
    # x another list with same length
    
    Explanation:
    >>> a
    [1, 2, 3, 4, 5, 6, 7, 8, 9]
    >>> x
    ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'j']
    

    Zip function will return a list of tuples

    >>> zip(a,x)
    [(1, 'a'), (2, 'b'), (3, 'c'), (4, 'd'), (5, 'e'), (6, 'f'), (7, 'g'), (8, 'h'), (9, 'j')]
    

    List comprehension is a shortcut to loop an element over list which after "in", and evaluate the element with expression, then return the result to a list, also you can add condition on which result you want to return

    >>> [expression(element) for **element** in **list** if condition ]
    

    This code does nothing but return all pairs that zipped up.

    >>> [(i,j) for (i,j) in zip(a,x)]
    [(1, 'a'), (2, 'b'), (3, 'c'), (4, 'd'), (5, 'e'), (6, 'f'), (7, 'g'), (8, 'h'), (9, 'j')]
    

    What we do is to add a condition on it by specify "if" follow by a boolean expression

    >>> [(i,j) for (i,j) in zip(a,x) if i >= 4]
    [(4, 'd'), (5, 'e'), (6, 'f'), (7, 'g'), (8, 'h'), (9, 'j')]
    

    using Itertools

    >>> [ _ for _ in itertools.compress(d, map(lambda x: x>=4,a)) ]
    # a will be the list compare to 4
    # d another list with same length
    

    Use itertools.compress with single line in Python to finish close this task

    >>> a = [1, 2, 3, 4, 5, 6, 7, 8, 9]
    >>> d = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'j'] # another list with same length
    >>> map(lambda x: x>=4, a)  # this will return a boolean list 
    [False, False, False, True, True, True, True, True, True]
    
    
    >>> import itertools
    >>> itertools.compress(d, map(lambda x: x>4, a)) # magic here !
    <itertools.compress object at 0xa1a764c>     # compress will match pair from list a and the boolean list, if item in boolean list is true, then item in list a will be remain ,else will be dropped
    #below single line is enough to solve your problem
    >>> [ _ for _ in itertools.compress(d, map(lambda x: x>=4,a)) ] # iterate the result.
    ['d', 'e', 'f', 'g', 'h', 'j']
    

    Explanation for itertools.compress, I think this will be clear for your understanding:

    >>> [ _ for _ in itertools.compress([1,2,3,4,5],[False,True,True,False,True]) ]
    [2, 3, 5]