Rand method on array with use of range operator + array index - ruby

I have this little problem with this code: I want to pass parameter to this random_select method in form of array, and I want to have one random index returned. I know that It won't work due to the way that range operator works , for such purposes we have sample method. But can anyone explain me why is this code returning nil as one of its random value?
def random_select(array)
array[rand(array[0]..array[4])]
end
p random_select([1,2,3,4,5])

Because your range is accessing to array values, not to array indexes:
array = [1, 2, 3, 4, 5]
array[0] #=> 1
array[4] #=> 5
array[0]..array[4] #=> 1..5
What you want is achievable in this way:
def random_select(array)
indexes = 0...array.size #=> 0...5
array[rand(indexes)]
end
array = [1, 2, 3, 4, 5]
Array.new(100) { random_select array }.uniq.sort == array #=> true

Have you tried using sample?
def random_select(array)
array.sample
end
Choose a random element or n random elements from the array.
The elements are chosen by using random and unique indices into the
array in order to ensure that an element doesn’t repeat itself unless
the array already contained duplicate elements.
If the array is empty the first form returns nil and the second form
returns an empty array.
The optional rng argument will be used as the random number generator.

Related

Ruby - pushing values from an array combination to a new array

I am trying to print all the different sums of all combinations in this array [1,2,3]. I want to first push every sum result to a new array b, then print them using b.uniq so that non of the sum results are repeated.
However, with the code I have, the 3 repeats itself, and I think it is because of the way it is pushed into the array b.
Is there a better way of doing this?
a = [1,2,3]
b = []
b.push a
b.push a.combination(2).collect {|a,b| (a+b)}
b.push a.combination(3).collect {|a,b,c| (a+b+c)}
puts b.uniq
p b #[[1, 2, 3], [3, 4, 5], [6]]
Can someone please help me with this? I am still new in ruby.
Because an Array of arbitrary length can be summed using inject(:+), we can create a more general solution by iterating over the range 1..n, where n is the length of the Array.
(1..(a.size)).flat_map do |n|
a.combination(n).map { |c| c.inject(&:+) }
end.uniq
#=> [1, 2, 3, 4, 5, 6]
By using flat_map, we can avoid getting the nested Array result, and can call uniq directly on it. Another option to ensure uniqueness would be to pass the result to a Set, for which Ruby guarantees uniqueness internally.
require "set"
sums = (1..(a.size)).flat_map do |n|
a.combination(n).map { |c| c.inject(&:+) }
end
Set.new(sums)
#=> #<Set: {1, 2, 3, 4, 5, 6}>
This will work for an any Array, as long as all elements are Fixnum.
If all you want is an array of the possible sums, flatten the array before getting the unique values.
puts b.flatten.uniq
What is happening is uniq is running over a multi-dimensional array. This causes it to look for duplicate arrays in your array. You'll need the array to be flattened first.

Adding unparallel elements between two arrays

I have a pair of arrays,
array_1 = [1,2,3,4,5]
array_2 = [10,9,8,7,6]
and I'm trying to subtract the nth element of one array from the (n-1)-th element of the second array, starting with the n-th element, yielding an array of:
[9-1, 8-2, 7-3, 6-4] = [8, 6, 4, 2]
I wrote it in a procedural fashion:
array_1.pop
array_2.shift
[array_2,array_1].transpose.map { |a,b| a-b }
but I do not wish to alter the arrays. Is there a method or another way to go about this?
Another way:
enum1 = array_1.to_enum
enum2 = array_2.to_enum
enum2.next
arr = []
loop do
arr << enum2.next - enum1.next
end
arr
#=> [8, 6, 4, 2]
Use the non-destructive drop for the receiver, and zip, which will stop when the receiver runs out of an element even if the argument has more.
array_2.drop(1).zip(array_1).map{|a, b| a - b}
I think you may be overthinking it a bit; as long as both arrays are the same length, you can just iterate over the indices you care about, and reference the other array by index - offset.
array_1 = [1,2,3,4,5]
array_2 = [10,9,8,7,6]
n = 1
(n...array_1.length).map {|i| array_2[i] - array_1[i - 1] }
You can set n to whatever number you like and compute from that point onwards, so even if the arrays were tremendously large, you don't have to generate any intermediate arrays, and you don't have to perform any unnecessary work.

Each with index with object in Ruby

I am trying to iterate over an array and conditionally increment a counter. I am using index to compare to other array's elements:
elements.each_with_index.with_object(0) do |(element, index), diff|
diff += 1 unless other[index] == element
end
I can't get diff to change value even when changing it unconditionally.
This can be solved with inject:
elements.each_with_index.inject(0) do |diff, (element, index)|
diff += 1 unless other[index] == element
diff
end
But I am wondering if .each_with_index.with_object(0) is a valid construction and how to use it?
From ruby docs for each_with_object
Note that you can’t use immutable objects like numbers, true or false
as the memo. You would think the following returns 120, but since the
memo is never changed, it does not.
(1..5).each_with_object(1) { |value, memo| memo *= value } # => 1
So each_with_object does not work on immutable objects like integer.
You want to count the number of element wise differences, right?
elements = [1, 2, 3, 4, 5]
other = [1, 2, 0, 4, 5]
# ^
I'd use Array#zip to combine both arrays element wise and Array#count to count the unequal pairs:
elements.zip(other).count { |a, b| a != b } #=> 1

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]

what's different between each and collect method in Ruby [duplicate]

This question already has answers here:
Array#each vs. Array#map
(7 answers)
Closed 6 years ago.
From this code I don't know the difference between the two methods, collect and each.
a = ["L","Z","J"].collect{|x| puts x.succ} #=> M AA K
print a.class #=> Array
b = ["L","Z","J"].each{|x| puts x.succ} #=> M AA K
print b.class #=> Array
Array#each takes an array and applies the given block over all items. It doesn't affect the array or creates a new object. It is just a way of looping over items. Also it returns self.
arr=[1,2,3,4]
arr.each {|x| puts x*2}
Prints 2,4,6,8 and returns [1,2,3,4] no matter what
Array#collect is same as Array#map and it applies the given block of code on all the items and returns the new array. simply put 'Projects each element of a sequence into a new form'
arr.collect {|x| x*2}
Returns [2,4,6,8]
And In your code
a = ["L","Z","J"].collect{|x| puts x.succ} #=> M AA K
a is an Array but it is actually an array of Nil's [nil,nil,nil] because puts x.succ returns nil (even though it prints M AA K).
And
b = ["L","Z","J"].each{|x| puts x.succ} #=> M AA K
also is an Array. But its value is ["L","Z","J"], because it returns self.
Array#each just takes each element and puts it into the block, then returns the original array. Array#collect takes each element and puts it into a new array that gets returned:
[1, 2, 3].each { |x| x + 1 } #=> [1, 2, 3]
[1, 2, 3].collect { |x| x + 1 } #=> [2, 3, 4]
each is for when you want to iterate over an array, and do whatever you want in each iteration. In most (imperative) languages, this is the "one size fits all" hammer that programmers reach for when you need to process a list.
For more functional languages, you only do this sort of generic iteration if you can't do it any other way. Most of the time, either map or reduce will be more appropriate (collect and inject in ruby)
collect is for when you want to turn one array into another array
inject is for when you want to turn an array into a single value
Here are the two source code snippets, according to the docs...
VALUE
rb_ary_each(VALUE ary)
{
long i;
RETURN_ENUMERATOR(ary, 0, 0);
for (i=0; i<RARRAY_LEN(ary); i++) {
rb_yield(RARRAY_PTR(ary)[i]);
}
return ary;
}
# .... .... .... .... .... .... .... .... .... .... .... ....
static VALUE
rb_ary_collect(VALUE ary)
{
long i;
VALUE collect;
RETURN_ENUMERATOR(ary, 0, 0);
collect = rb_ary_new2(RARRAY_LEN(ary));
for (i = 0; i < RARRAY_LEN(ary); i++) {
rb_ary_push(collect, rb_yield(RARRAY_PTR(ary)[i]));
}
return collect;
}
rb_yield() returns the value returned by the block (see also this blog post on metaprogramming).
So each just yields and returns the original array, while collect creates a new array and pushes the results of the block into it; then it returns this new array.
Source snippets: each, collect
The difference is what it returns. In your example above
a == [nil,nil,nil] (the value of puts x.succ) while b == ["L", "Z", "J"] (the original array)
From the ruby-doc, collect does the following:
Invokes block once for each element of
self. Creates a new array containing
the values returned by the block.
Each always returns the original array. Makes sense?
Each is a method defined by all classes that include the Enumerable module. Object.eachreturns a Enumerable::Enumerator Object. This is what other Enumerable methods use to iterate through the object. each methods of each class behaves differently.
In Array class when a block is passed to each, it performs statements of the block on each element, but in the end returns self.This is useful when you don't need an array, but you maybe just want to choose elements from the array and use the as arguments to other methods. inspect and map return a new array with return values of execution of the block on each element. You can use map! and collect! to perform operations on the original array.
I think an easier way to understand it would be as below:
nums = [1, 1, 2, 3, 5]
square = nums.each { |num| num ** 2 } # => [1, 1, 2, 3, 5]
Instead, if you use collect:
square = nums.collect { |num| num ** 2 } # => [1, 1, 4, 9, 25]
And plus, you can use .collect! to mutate the original array.

Resources