buterfly85
buterfly85

Reputation: 193

How does Array#select method exactly works in ruby? And why it returns an empty array or the original one?

I have this code

arr = [1, 2, 3].select do |n|
  n + 2
  puts n
end

The output is

1
2
3

and the return value is

[]

Then I have this code

arr = [1, 2, 3].select do |n|  
  n + 2
end

and the return value is

[1, 2, 3]

So I know that Array#select invokes the block passing in successive elements from self, returning an array containing those elements for which the block returns a true value. How does it behave in those code examples so I could understand why it returns these values.

Upvotes: 0

Views: 5042

Answers (2)

nabilkaz
nabilkaz

Reputation: 33

Array#select returns a new array with all the elements that returned true from the block. It does this by iterating over each element, passing it to the block, running the block if the block returns true it puts the element in the new array if not it will skip it and once done it will return a new array.

With that said there are a few other things we should know first before delving into the problem you're having.

1) In Ruby there's a concept called Truthiness. That means that every element except for nil and false evaluates to true. Take for example if I ran this conditional

if 'happy puppy'
  puts "I'm the happiest puppy"
end

You'd see that I'm the happiest puppy is output. That's because the string, not being false or nil, will evaluate to true. Conversely if ran this code

if nil
  puts "Truthiness means all things evaluate to true except nil and false"
end

In this example, the conditional wouldn't output the string because nil doesn't evaluate to true.

2) Pay careful attention to what a method outputs and returns. In the case of Kernel#Puts it outputs n and returns nil. When the block being passed to Array#select is invoked it runs each line of code in the block including puts. That's why we see each number output. Then, this is the important part, it returns nil. Now remember the rules of Truthiness? Because this is the last line of code in the block it's the implicit return of the entire block. That means the block will return nil which evaluates to false.

3) Now on to Array#select, it works by iterating over each element in an array and invoking the block on it. Based on the return value of the block it'll decide whether or not the element belongs in the return array. In your first example, puts is used on the last line and returns nil which means that the block will always evaluate to false. That's why it outputs the element but then returns an empty array. In the second example, the last line in the block is n+2 which will evaluate to an integer. This is where truthiness comes in to play, an integer (or anything besides false or nil) will always evaluate to true. This means the block always returns true. That's why all the elements are returned in the array.

Upvotes: 1

msergeant
msergeant

Reputation: 4801

Array#select creates a new array using the elements of your array that return truthy from the block.

In your first case, the last line of your block is a puts statement which always returns nil. Hence the [].

In your second case, the last line of your block is always a number, so always truthy. Hence the output equals the input.

Upvotes: 5

Related Questions