Find Indices of Elements That Match a Given Condition

Find indices of elements that match a given condition

Ruby 1.9:

arr = ['x', 'o', 'x', '.', '.', 'o', 'x']
p arr.each_index.select{|i| arr[i] == 'x'} # =>[0, 2, 6]

Code

Python: How to find indices of elements that satisfy conditions in each row, and transformed them to a dict?

np.unique can be used with indexes to get both the dictionary keys and locations, then use np.split to divide the array, then zip together the keys and the arrays to build the dictionary from the tuples:

g0 = np.argwhere(myarray > 0)
keys, locs = np.unique(g0[:, 0], return_index=True)
d = dict(zip(keys, np.split(g0[:, 1], locs[1:])))

np.nonzero may be faster than np.argwhere in this case:

i, v = np.nonzero(myarray > 0)
keys, locs = np.unique(i, return_index=True)
d = dict(zip(keys, np.split(v, locs[1:])))

However, a simple dictionary comprehension is likely the fastest option on smaller arrays:

d = {i: np.nonzero(r > 0)[0] for i, r in enumerate(myarray)}

All options produce d:

{0: array([0, 1, 3]),
1: array([0, 1, 2, 3]),
2: array([0]),
3: array([0, 1, 2]),
4: array([0, 1, 2])}

Setup and imports:

import numpy as np

np.random.seed(20211021)
myarray = np.random.randint(0, 5, size=(5, 4))

Find indices of elements that match condition of 2D array by row

Using np.where + np.split

x, y = np.where(A.T < B)

s = np.flatnonzero(np.append([False], x[1:] != x[:-1]))

np.split(y, s)

[array([0, 1, 2], dtype=int64),
array([1, 2], dtype=int64),
array([2], dtype=int64)]

Find indexes of array that match a condition, then push into another array

Matching Condition

This answer presumes that you're looking to get the indices of the elements which are of equal length to the element in the array with the maximum length.


Getting the Indices

To get the length of the longest element, we first get the lengths of each element, then reduce the array so as to get only the maximum length.

Next, we map each element of the array to one of two things; if the element is the same length as the maximum length, we take its index. If it isn't, then we map false instead. We do that so we can filter out those values.

Lastly, we filter out values which are false. These values were not as long as the maximum length, so we don't want them.


As T.J.Crowder alluded to, a forEach might do this in a way that's more direct, and potentially more readable. Experimenting with chaining array methods in this way will allow you to make a good decision as to the kind of code which will work best for the situation with which you are faced.

If you are working with very large data sets, then iterating over your data multiple times in order to improve code readability, at the expense of performance, is probably a bad idea.

const arr = ["00", "000", "", "0", "000"]
const maxLength = arr .map(e => e.length) .reduce((a, b) => a > b ? a : b) const result = arr .map((val, i) => val.length === maxLength ? i : false) // log the index of the item if the item's length is 1 .filter(i => i !== false) // remove non-truthy elements console.dir(result)

find first element and index matching condition in list

You could do it in a list comprehension. This is basically the same as your code but condensed into one line, and it builds a list of results that match the criteria.

The first way gets all the matches

mylist = [-1,-2,3,4,5,6]

results = [(i, el) for i, el in enumerate(mylist) if el > 0]

Another way would be to use a generator expression which is probably faster, and just unpack it. This gets the first one.

*next((i, el) for i, el in enumerate(mylist) if el > 0))

This loops the list and checks the condition, then puts the index and element into a tuple. Doing this inside parentheses turns it into a generator, which is much faster because it hasn't actually got to hold everything in memory, it just generates the responses as you need them. Using next() you can iterate through them. As we only use next() once here it just generates the first match. Then we unpack it with *

As there are two other valid answers here I decided to use timeit module to time each of them and post the results. For clarity I also timed the OP's method. Here is what I found:

import timeit
# Method 1 Generator Expression
print(timeit.timeit('next((i, el) for i, el in enumerate([-1,-2,3,4,5,6]) if el > 0)', number=100000))
0.007089499999999999

# Method 2 Getting index of True
print(timeit.timeit('list(x > 0 for x in [-1,-2,3,4,5,6]).index(True)', number=100000))
0.008104599999999997

# Method 3 filter and lambda
print(timeit.timeit('myidx , myel = list(filter(lambda el: el[1] > 0, enumerate([-1,-2,3,4,5,6])))[0]', number=100000))
0.0155314

statement = """
for idx, el in enumerate([-1,-2,3,4,5,6]):
if el > 0:
myidx, myel = idx, el
break
"""

print(timeit.timeit(statement, number=100000))
0.04074070000000002

Get all the indexes from the array on matching the condition

You don't need to convert the array to List to do this operation, all you can do is:

int[] indexes = IntStream.range(0, updateResultArray.length)
.filter(i -> updateResultArray[i] > 0)
.toArray();

get indexes with condition

You can use enumerate in a conditional list comprehension to get the index locations.

my_list = [5, 8, 2, 7, 8, 8, 2, 4]
search_value = 8
>>> [i for i, n in enumerate(my_list) if n == search_value]
[1, 4, 5]

If the search value is not in the list, then an empty list will be returned (not exactly None, but still a falsey).

Using pandas, you can use boolean indexing to get the matches, then extract the index to a list:

df[df[0] == search_value].index.tolist()

Using an empty list will satisfy the condition for None (they both evaluate to False). If you really need None, then use the suggestion of @cᴏʟᴅsᴘᴇᴇᴅ.

How to find the indices of all elements matching from one list to another in Dart/Flutter

Try this:

main() {
var firstList = ["Travel", "Shopping", "Transport"];
var secondList = [
"Travel",
"Shopping",
"Shopping",
"Travel",
"Transport",
"Transport",
"Travel",
"Travel"
];
var thirdList = [];
for (var i = 0; i < secondList.length; i++) {
if (secondList[i] == "Travel") {
thirdList.add(i);
}
}
print(thirdList);
}

EDIT: For it to work for every item in firstList

Try this:

main() {
var firstList = ["Travel", "Shopping", "Transport"];
var secondList = [
"Travel",
"Shopping",
"Shopping",
"Travel",
"Transport",
"Transport",
"Travel",
"Travel"
];
var thirdList = [];
for (var i = 0; i < firstList.length; i++) {
var sublist = [];
for (var j = 0; j < secondList.length; j++) {
if (secondList[j] == firstList[i]) {
sublist.add(j);
}
}
thirdList.add(sublist);
}
print(thirdList); // [[0, 3, 6, 7], [1, 2], [4, 5]]
}

How do I find an index of an element in an array matching a condition and starting the search from a particular point in the array?

Using select would return all values where the block returns true for example:

p arr = ["abc", "d", "efg", "h", "abcde", "k"]
# => ["abc", "d", "efg", "h", "abcde", "k"]
p arr.each_index.select{|i| i >= 2 and arr[i].length == 1}
# => [3, 5]

Instead use detect if you want to return only the first value where the block returns true:

p arr = ["abc", "d", "efg", "h", "abcde", "k"]
# => ["abc", "d", "efg", "h", "abcde", "k"]
p arr.each_index.detect{|i| i >= 2 and arr[i].length == 1}
# => 3


Related Topics



Leave a reply



Submit