0

I have an array, and I need an array of subscripts of the original array's elements that satisfy a certain condition.

map doesn't do because it yields an array of the same size. select doesn't do because it yields references to the individual array elements, not their indices. I came up with the following solution:

my_array.map.with_index {|elem,i| cond(elem) ? i : nil}.compact 

If the array is large and only a few elements fulfill the conditions, another possibility would be

index_array=[] my_array.each_with_index {|elem,i| index_array << i if cond(elem)} 

Both work, but isn't there a simpler way?

2
  • could you please share a sample array? Commented May 30, 2017 at 6:50
  • 1
    I guess technically my_array.map.with_index {|elem,i| cond(elem) ? i : nil}.compact could be simplified to my_array.map.with_index {|elem,i| i if cond(elem)}.compact but it is essentially the same Commented May 30, 2017 at 18:27

3 Answers 3

4

Nope, there is nothing inbuilt or much simpler that what you already got.

Variation:

my_array.each_with_index.with_object([]) do |(elem, idx), indices| indices << idx if cond(elem) end 
Sign up to request clarification or add additional context in comments.

1 Comment

1. Consider using with_object rather than inject to use the same array, instead of recreating it on each iteration. 2. Also, do |(elem, idx), indices|.
3

Another possible alternative:

my_array.select.with_index {|elem, _| cond(elem) }.map(&:last) 

Comments

2

You can use Array#each_index with select

arr = [1, 2, 3, 4] arr.each_index.select {|i| arr[i].odd? } # => [0, 2] 

1 Comment

This is way worse than each.with_index.with_object because it performs array index lookup on each iteration.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.