This question already has answers here:
What does the (unary) * operator do in this Ruby code?
(3 answers)
What does the * (star) mean in Ruby? [duplicate]
(1 answer)
Closed 7 years ago.
I read this code that is about quicksort with monkey-patching for the Array class.
class Array
def quicksort
return [] if empty?
pivot = delete_at(rand(size))
left, right = partition(&pivot.method(:>))
return *left.quicksort, pivot, *right.quicksort
end
end
I don't know what the star (*) sign seen at the start of *left.quicksort is. Can't we just use left.quicksort?
The star (in this case) stands for array unpacking. The idea behind it is that you want to get one array with the given elements, instead of array of array, element, array:
left = [1, 2, 3]
pivot = 4
right = [5, 6, 7]
[left, pivot, right] # => [[1, 2, 3], 4, [5, 6, 7]]
[*left, pivot, *right] # => [1, 2, 3, 4, 5, 6, 7]
The * takes a list of arguments and splits them into individual elements.
This allows you to return one un-nested array even when the left and right themselves return an array.
Regarding can't we just use left.quicksort did you give it a try?
def a()
return *[1,2,3], 4, *[5,6]
end
def b()
return [1,2,3], 4, *[5,6]
end
b()
=> [[1, 2, 3], 4, 5, 6]
a()
=> [1, 2, 3, 4, 5, 6]
Without the asterisk, you will have three values returned... the first and last value will be a single array with multiple values
[array1], pivot, [array2]
With the asterisk, the array values will be returned as separate components...
array1_value_1, array1_value_2, array1_value_3, ..., pivot, array2_value_1, array2_value2, array2_value_3, ...
Related
Good day. I've tried writing this code in ruby
x = [1, 2, 3, 4, 5]
x.each do |a|
a + 1
end
When I type this in irb, I don't understand why does it return
=> [1, 2, 3, 4, 5]
I thought it would return
=> [2, 3, 4, 5, 6] # because of a + 1
each yields the array's elements to the given block (one after another) without modifying the array. At the end, it returns the array, as mentioned in the docs:
[...] passes each successive array element to the block; returns self
You are probably looking for map, which works similar to each but instead of returning self, it ...
[...] returns a new Array whose elements are the return values from the block
Example:
x = [1, 2, 3, 4, 5]
x.map { |a| a + 1 }
#=> [2, 3, 4, 5, 6]
Note that it returns a new array without actually modifying x. There's also map! (with !) which does modify the receiver.
This question already has answers here:
What does map(&:name) mean in Ruby?
(17 answers)
Closed 2 years ago.
I done a coding challenge in Ruby not too long ago and wanted a better understanding of how the syntax below works, particularly with the last part of the expression (&:first).
def remove_every_other(arr)
arr.each_slice(2).map(&:first)
end
For some background the task was to take an array and remove every second element from the array.
Tests:
Test.assert_equals(remove_every_other(['Hello', 'Goodbye', 'Hello Again']), #=> ['Hello', 'Hello Again'])
Test.assert_equals(remove_every_other([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]), #=> [1, 3, 5, 7, 9])
Test.assert_equals(remove_every_other([[1, 2]]), #=> [[1, 2]])
Test.assert_equals(remove_every_other([['Goodbye'], {'Great': 'Job'}]), #=> [['Goodbye']])
Test.assert_equals(remove_every_other([]), [])
& is a reference to a method.
:first is a symbol.
So &:first is simply a reference to the method named first in any object.
So this is the same thing as saying arr.each_slice(2).map {|it| it.first }.
When you map a method to elements of a collection, Ruby will simply call that method on the elements of the collection. In your case, arr.each_slice(2) will return elements of arr two by two (see the doc for each_slice), so if your array is e.g. [1, 2, 3, 4, 5, 6, 7, 8] it is a collection containing [[1, 2], [3, 4], [5, 6], [7, 8]]. Mapping :first on that collection means calling the first method on each element, and [1, 2].first simply returns 1 while [7, 8].first returns 7.
As the map method returns a collection with each element replaced with the result of the call to the method, you'll find yourself with a collection containing the first of each pair. This is how it removes every other element.
Note that if the original collection has an odd number of elements then the last one will be an array of one instead of two (see doc for each_slice), so if the array is [1, 2, 3] the slices are [[1, 2], [3]] and calling .first on each will result in [1, 3].
I'm currently working on a simple multiplying method.
CODE:
def multiply(*numbers)
product = 1
numbers.each{|number|
product *= number
}
return product
end
puts multiply([2, 3, 4, 5])
OUTPUT:
*': Array can't be coerced into Fixnum (TypeError)
from calculator.rb:26:inblock in multiply'
from calculator.rb:24:in each'
from calculator.rb:24:inmultiply'
from calculator.rb:31:in `'
I get this error. It seems the method isn't allowing me to use ".each" on the array.
Also, I want to keep the parameter as *numbers in case it's not an array but two numbers to multiply. I should bring it to your attention that the method works fine when the parameter being passed are two numbers and not an array (i.e. multiply(2, 4)
multiply expects an arbitrary number of parameters. You pass only one parameter, which is an array. On the first iteration, number is the whole array. Hence the error message.
You have to fix the call, either
multiply(*[2, 3, 4, 5])
or, simpler,
multiply(2, 3, 4, 5)
The problem is different. In numbers.each you iterate over list of arguments, however with multiply([2, 3, 4, 5]) you are passing one argument, which is an array. The list of arguments is [[2, 3, 4, 5]]. So in the only iteration, you are trying to do:
1 *= [2, 3, 4, 5]
This basically makes no sense to Ruby, so it throws an error.
You should call multiply method with a list of arguments, not ona array argument:
multiply(2, 3, 4, 5)
Then it will work.
If you want to be able to use array as input, you can use to flatten method on the numbers array.
def multiply(*numbers)
product = 1
numbers.flatten.each{|number|
product *= number
}
return product
end
puts multiply([2, 3, 4, 5]) #=> 120
The flatten method will take a 2d array and turn into a simple array.
This will also work
multiply([2, 3, 4, 5], 2, 2) #=> 480
In this case,
numbers = [[2, 3, 4, 5], 2, 2]
After you apply the flatten method, you get
[2, 3, 4, 5, 2, 2]
Then you can begin to multiply each number.
As it is normal in Ruby, there is usually a method that do what you are looking to do. In this case, inject, and reduce can accomplish what you are looking for.
def multiply(*numbers)
numbers.flatten.reduce(&:*)
end
Nevermind! I realized that when passing an array using *args, it becomes and array of arrays.
This question already has answers here:
How are array.each and array.map different? [duplicate]
(4 answers)
Closed 9 years ago.
Examining the following code
[1,2,3,4].map # => #<Enumerator: [1, 2, 3, 4]:map>
[1,2,3,4].each # => #<Enumerator: [1, 2, 3, 4]:each>
we can see that both are an enumerator. One is map and other is each. The method to_enum also returns an enumerator each. Is there any difference between these two enumerators?
Yes, when you iterate over the map enumerator, it will take the result and populate it into a new array:
[1,2,3,4].map.each { |n| n * 2 } # => [2, 4, 6, 8]
When you iterate over the each enumerator, it will return the original array
[1,2,3,4].each.each { |n| n * 2 } # => [1, 2, 3, 4]
Map exists to take an array of one type and convert it to an array of a different type, each exists to simply iterate over the array (doing something with a side effect for each element, such as printing it out).
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
ruby array element grouping
Example. Given array a:
a = [1, 2, 3]
Its length is 3 so I want to print all 2-length arrays. These are:
[1, 2]
[1, 3]
[2, 3]
I don't know if there is some method in Ruby to get subset arrays. If there is not such a method what is most efficient way to do achieve this.
That's just a simple combination of 2 elements:
>> xs = [1, 2, 3]
>> xs.combination(xs.size - 1).to_a
=> [[1, 2], [1, 3], [2, 3]]
[EDIT] As #Joshua pointed out in a comment, the docs state that the order is not guaranteed (!). So here is a functional implementation that generates the combinations in the order you asked for. For completeness, I'll make it lazy as the original combination method:
require 'enumerable/lazy'
class Array
def combinations_of(n)
if n == 0
[[]].lazy
else
0.upto(self.size - 1).lazy.flat_map do |idx|
self.drop(idx + 1).combinations_of(n - 1).map do |xs|
[self[idx]] + xs
end
end
end
end
end