What is the difference between `each` and `map` enumerators? [duplicate] - ruby

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).

Related

Iterating over an array and building a new array with incremented values [duplicate]

This question already has answers here:
Array#each vs. Array#map
(7 answers)
Closed 4 years ago.
What is the difference between this code:
p arr = [1, 2, 3, 4, 5]
p arr.map! { |a| a + 2 }
and this code?
arr = [1, 2, 3, 4, 5]
new_arr = []
arr.each do |n|
new_arr << n + 2
end
p arr
p new_arr
They both result in the same answer. Are they just two different ways to achieve the same solution or is there a process or application difference?
The #map function "invokes the given block once for each element of self, replacing the element with the value returned by the block".
In your second example the #each method modifies each element of the array by adding + 2 and returns the modified array. The second example is based on creating a new array and filling it with modified values from the first array.
The process is pretty much the same, the main difference is that in the first example you permanently modify the array while in the second example you get to keep the first array unchanged and create a new one with modified values.

What does the "*" mean in this recursive ruby function? [duplicate]

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, ...

Get k-1 length subset arrays of k length array [duplicate]

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

Difference Between map and each [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Ruby - What is the difference between map, each and collect?
I have looked in Ruby-Doc also but i cant understand the difference between
map
each
iterators.It would be great if you could give an example and explain.
each simply iterates over the given enumerable, running the block for each value. It discards the return value of the block, and each simply returns the original object it was called on:
[1, 2, 3].each do |x|
x + 1
end # => [1, 2, 3]
This is simply a nicer, more universal way of doing a traditional iterating for loop, and each is much preferred over for loops in Ruby (in fact, I don't think I've ever used a for loop in Ruby).
map, however, iterates over each element, using the return value of the block to populate a new array at each respective index and return that new array:
[1, 2, 3].map do |x|
x + 1
end # => [2, 3, 4]
So it “maps” each element to a new one using the block given, hence the name “map”. Note that neither each nor map themselves modify the original collection. This is a concise, functional alternative to creating an array and pushing to it in an iterative loop.
each returns the original object. It's used to run an operation using each element of an array without collecting any of the results. For example, if you want to print a list of numbers, you might do something like this:
arr = [1, 2, 3, 4]
arr.each { |n| puts n }
Now, that puts method above actually returns nil. Some people don't know that, but it doesn't matter much anyway; there's no real reason to collect that value (if you wanted to convert arr to strings, you should be using arr.map(&:to_s) or arr.map { |n| n.to_s }.
map returns the results of the block you pass to it. It's a great way to run an operation on each element in an array and retrieve the results. If you wanted to multiple every element of an array by 2, this is the natural choice. As a bonus, you can modify the original object using map!. For example:
arr = [1, 2, 3, 4]
arr.map! { |n| n * 2}
# => [2, 4, 6, 8]

How do I check an array for duplicates? [duplicate]

This question already has answers here:
How to find and return a duplicate value in array
(23 answers)
Closed 8 years ago.
I've got an array A. I'd like to check if it contains duplicate values. How would I do so?
Just call uniq on it (which returns a new array without duplicates) and see whether the uniqed array has less elements than the original:
if a.uniq.length == a.length
puts "a does not contain duplicates"
else
puts "a does contain duplicates"
end
Note that the objects in the array need to respond to hash and eql? in a meaningful for uniq to work properly.
In order to find the duplicated elements, I use this approach (with Ruby 1.9.3):
array = [1, 2, 1, 3, 5, 4, 5, 5]
=> [1, 2, 1, 3, 5, 4, 5, 5]
dup = array.select{|element| array.count(element) > 1 }
=> [1, 1, 5, 5, 5]
dup.uniq
=> [1, 5]
If you want to return the duplicates, you can do this:
dups = [1,1,1,2,2,3].group_by{|e| e}.keep_if{|_, e| e.length > 1}
# => {1=>[1, 1, 1], 2=>[2, 2]}
If you want just the values:
dups.keys
# => [1, 2]
If you want the number of duplicates:
dups.map{|k, v| {k => v.length}}
# => [{1=>3}, {2=>2}]
Might want to monkeypatch Array if using this more than once:
class Array
def uniq?
self.length == self.uniq.length
end
end
Then:
irb(main):018:0> [1,2].uniq?
=> true
irb(main):019:0> [2,2].uniq?
=> false

Resources