Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

what is the mean of * and flatten in ruby

Tags:

flatten

ruby

I am new to ruby language so when I was trying to sort a hash by value I used this method to sort:

movie_popularity.sort_by{|m,p| p}.reverse

but the the sort method returns an array while I need a hash to be returned so I used this command:

movie_popularity=Hash[*movie_popularity.sort_by{|m,p| p}.reverse.flatten]

my Question is what is the meaning of * and flatten in the above line?

Thanks =)

like image 529
user1452250 Avatar asked Jun 13 '12 00:06

user1452250


People also ask

What does flatten mean Ruby?

The flatten() is an inbuilt method in Ruby returns a new set that is a copy of the set, flattening each containing set recursively. Syntax: s1.flatten() Parameters: The function does not takes any parameter. Return Value: It returns a boolean value. It returns true if the set is empty or it returns false.

How does Ruby flatten work?

Flattening an Array with Recursion Like the single flatten, it checks if an element is an array, and if not, appends the value of the element to a results array. However, if the element is an array, the method calls itself pulling in this element and the existing results array.

What does :+ mean in Ruby?

inject accepts a symbol as a parameter, this symbol must be the name of a method or operator, which is this case is :+ so [1,2,3]. inject(:+) is passing each value to the method specified by the symbol, hence summing all elements in the array.


1 Answers

The * is called the "splat operator"; I'm not sure I could give you the technical definition (though I'm sure you'd find it soon enough with Google's help), but the way I'd describe it is that it basically takes the place of hand-writing multiple comma-separated values in code.

To make this more concrete, consider the case of Hash[] which you've used in your example. The Hash class has a [] class method which takes a variable number of arguments and can normally be called like this:

# Returns { "foo" => 1, "bar" => 2 }
h = Hash["foo", 1, "bar", 2]

Notice how that isn't an array or a hash or anything that I passed in; it's a (hand-written) sequence of values. The * operator allows you to achieve basically the same thing using an array--in your case, the one returned by movie_popularity.sort_by{|m,p| p}.reverse.flatten.

As for that flatten call: when you call sort_by on a hash, you're really leveraging the Enumerable module which is included in a variety of classes (most notably Array and Hash) that provide enumeration. In the case of a hash, you've probably noticed that instead of iterating over one like this:

hash.each { |value| ... }

Instead you do this:

hash.each { |key, value| ... }

That is, iterating over a hash yields two values on each iteration. So your sort_by call on its own would return a sequence of pairs. Calling flatten on this result collapses the pairs into a one-dimensional sequence of values, like this:

# Returns [1, 2, 3, 4]
[[1, 2], [3, 4]].flatten
like image 79
Dan Tao Avatar answered Oct 18 '22 13:10

Dan Tao