1

Given:

my_array = ['america', 'bombay', 'bostwana', 'cameroon']

I can locate the index of the first element that, say, begins with 'bo' with

my_array.find_index { |l| l.start_with? 'bo' }

How can I locate all such elements?

2
  • 1
    Your last comment on @davidhu2000's now-deleted answer ("I'm in need of votes, so if you think it deserves it, kindly upvote the question.") is akin to "I need an "A", so please give me one if you think I deserve it". Don't beg, it's unbecoming. Commented Oct 14, 2016 at 17:31
  • If you just want the elements and not their indexes then then my_array.grep(/^bo/) will suffice. Commented Oct 14, 2016 at 17:43

4 Answers 4

1

If you want the elements:

my_array.find { |element| element.start_with? 'bo' }   # => "bombay"
my_array.select { |element| element.start_with? 'bo' } # => ["bombay", "bostwana"]

If you want the indices:

my_array.index { |element| element.start_with? 'bo' } # => 1
my_array.map.with_index.select { |element, _| element.start_with? 'bo' }.map(&:last)
  # => [1, 2]
Sign up to request clarification or add additional context in comments.

1 Comment

Thanks, ndn. Gosh, that (all-indices return implementation) looks scary! :) May I request you to upvote my question if you think it deserves to be? Total noob here (in case you didn't realize). Thanks.
1

You can use map.with_index with a conditional and compact the result.

my_array.map.with_index{ |element, index| index if element.start_with? 'bo' }.compact

How this works

map

map will take all of the values and "map" them to the value that is returned when each item is passed into the given block.

my_array.map { |element| element.start_with? 'bo' }
# => [false, true, true, false]

with_index

To get the index values you can use with_index like this:

my_array.map.with_index { |element, index| index }
# => [0, 1, 2, 3]

my_array.map.with_index { |element, index| index if element.start_with? 'bo' }
# => [nil, 1, 2, nil]

compact

Then, to get rid of the nil values you can call compact on the returned array.

my_array.map.with_index{ |element, index| index if element.start_with? 'bo' }.compact
# => [1, 2]

1 Comment

Brilliant! Thanks so much for the step-by-step, Scott. Much appreciated!
0
['america', 'bombay', 'bostwana', 'cameroon']
  .each_with_index # to get indices
  .grep(->(e) { e.first.start_with? "bo" }) # I ❤ Enumerable#grep
  .map(&:last) # get indices
#⇒ [1, 2]

I posted this to show the approach that is rarely used. Enumerable#grep accepts anything, that is used to select items basing on triple-equal case comparison.

Passing Proc instance there is cool, because Proc has a default Proc#=== implementation: it’s simply being invoked on receiver.

Comments

0

In the interest of readability, I would use the following:

my_array.each_index.select {|idx| my_array[idx].start_with?("bo") }

5 Comments

1. it requires temporary local variable, 2. it performs redundant secondary lookup on each iteration, 3. there are in fact 3 methods.
@mudasobwa, I count 4, n'est-ce pas?
@CarySwoveland I counted dots. Array#[] was scolded in the previous item :)
The operative word you've both missed is "chain." I'd rather do a "redundant" lookup once per iteration than iterate over the data twice. Regardless: readability.
Since readability, while important, isn't the only important factor, and because I can never resist once I start wondering, I benchmarked the answers: gist.github.com/jrunning/da9e9e3c00bda19c7d213ceebb38de90

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.