Ruby array merge method - arrays

I'm looking for a method that is equivalent to Array#|, and whose method name is in ordinary word.
a = [1, 2, 3]
b = [3, 4, 5]
a|b # => [1, 2, 3, 4, 5]
I'm not looking for new methods. I can write any sort of method that will accomplish this. That's not what I'm asking. I'm wondering if there's an alias. Is there a method like a.merge(b) that isn't a functioning method for arrays in 2.5.1?
It's described in the documentation for version 2.5.1 that | is the same as Array.union(another_array). But it throws an error.
a.union(b) # >> undefined method `union' for [1, 2, 3]:Array (NoMethodError)
Is there such a written method for a union?

Array#union works fine in Ruby 2.6, but if it's not in Ruby 2.5 and you insist on having a method named union, the following worked like a champ for me in Ruby 2.3.7:
[1,2,3].union [4,5,6] # => NoMethodError: undefined method `union' for [1, 2, 3]:Array
class Array
def union(other)
self | other
end
end
[1,2,3].union [4,5,6] # => [1, 2, 3, 4, 5, 6]
To get functionality comparable to 2.6's Array#union documented behavior in earlier versions of Ruby:
class Array
def union(*others)
others.inject(self, &:|)
end
end
[1,2].union [3,4], [5] # => [1, 2, 3, 4, 5]
[10,11].union # => [10, 11]

There's no exact equivalent for Array#|, even in Ruby 2.6.
Array#union is implemented in array.c#rb_ary_union_multi while Array#| is implemented in array.c#rb_ary_or.
They both use rb_ary_union under the hood for small arrays (less than 16 elements) and rb_ary_union_hash for larger arrays but rb_ary_union_multi accepts more than 2 arguments:
a = [1, 2, 3]
b = [3, 4, 5]
c = [4, 5, 6]
a.union(b, c)
# => [1, 2, 3, 4, 5, 6]
a.|(b, c)
# ArgumentError (wrong number of arguments (given 2, expected 1))

Related

Groovy 2D array combinations

I have a 2D array which looks like [[1, 2, 3], [10, 11]]. I want to get the next combinations: [[1, 2, 3, 10], [1, 2, 3, 11]]. The idea is to take all values from left array and combine it with each value from right array. I've tried different Groovy out of the box methods like combinations(), permutations() to get the expected result, but without any success. Please, help.
Why not simply:
def a = [[1, 2, 3], [10, 11]]
def res = a[ 1 ].collect{ a[ 0 ] + it }
assert res == [[1, 2, 3, 10], [1, 2, 3, 11]]
If one can cheat... Nesting the first list into another list can let us use .combinations() still:
def a = [[[1, 2, 3]], [10, 11]] //a[0] changed to [a[0]]
a.combinations().collect{it.flatten()} //[[1, 2, 3, 10], [1, 2, 3, 11]]
Now, if you can't store the values like that, you can still still make the change part of your code. All this assumes that the list is just a pair.
([a[0]] + a[1..<(a.size())]).combinations().collect{it.flatten()} //same result
I believe there are less unorthodox ways of doing it, but that's a quick and dirty solution.

Ruby array: getting all the elements that have the max value while chaining methods (namely, without having a handle on the sorted array)

Suppose that you need to get all the elements that have the max value in an array.
A possible method would be to sort the array then use Enumerable#take_while:
array = [ 1, 3, 2, 3, 2, 3 ].sort {|a,b| b - a}
array.take_while { |e| e == array[0] }
#=> [3, 3, 3]
Now, when you are beautifully chaining methods and don't want to stop the chain just for storing the sorted array (which you'll need for referencing its first element in the take_while block), how would you do it?
I posted the question and an answer below for reference, but I probably missed better ways, so feel free to post your own method
Another way:
arr = [ 1, 3, 2, 3, 2, 3 ]
arr.sort {|a,b| b - a}.tap { |a| a.select! { |e| e == a.first } }
#=> [3, 3, 3]
Note that arr is not mutated.
ruby < 2.5
My original response to the question: sort.slice_when.first
[ 1, 3, 2, 3, 2, 3 ].sort {|a,b| b - a}.slice_when {|a,b| b != a}.first
#=> [3, 3, 3]
note: As slice_when returns an Enumerator, this solution won't walk through all the sorted array when chaining it with first. There is a more performant solution below tough.
ruby >= 2.5
Combining #engineersmnky and #Cary methods: then and max+select
[ 1, 3, 2, 3, 2, 3 ].then { |arr| mx = arr.max; arr.select { |elm| elm == mx } }
#=> [3, 3, 3]
You can try this
pry(main)> [ 1, 2, 2, 3, 3, 3 ].sort.slice_when {|a,b| b > a}.to_a.last
=> [3, 3, 3]
A bit similar of the last solution but also different.
Source https://ruby-doc.org/core-3.0.2/Enumerable.html#method-i-slice_when

How to get a method to run on an array

I have been doing code Katas on codewars and I wanted to see if I could run them on my computer. But while I can devise various methods I can’t get any of them to run using Command Prompt with Ruby. E.g.
def sum_array(arr)
if arr.kind_of?(Array) and arr.length > 2
arr.inject(:+) - arr.min - arr.max
else
0
end
end
puts sum_array = [1, 2, 3, 4]
Instead of returning 5 it just gives me the unmodified array.
What is the correct way for me to get the method to work on an array?
Think = sign as 'get'.
By writing sum_array = [1, 2, 3, 4], you're assigning the [1, 2, 3, 4] to sum_array instead of calling it, which is why it puts out 1, 2, 3, 4.
To call that method with [1, 2, 3, 4] as argument, do:
puts sum_array([1, 2, 3, 4])
or
puts sum_array [1, 2, 3, 4]

How to use percent notation to make an array of integers in ruby?

In ruby you can use percent notation to easily make an array of strings:
[14] pry(main)> %w(some cats ran far)
=> ["some", "cats", "ran", "far"]
Using a method found in another post I was able to make an array of strings using percent notation and then converting them into Fixnums later:
[15] pry(main)> %w(1 2 3).map(&:to_i)
=> [1, 2, 3]
But I'd really like to be able to do something like
%i(1 2 3) #=> [1 2 3]
Is this possible? Thanks :)
As cremno said, no that is not possible.
If you want strictly a range of integers, such as 1 through 10, the best method will be
(1..10).to_a
# => [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
But if you want to specify exact integers I would do this
%w(1 5 10).map{|i| i.to_i}
# => [1, 5, 10]
But at that point I don't know why you wouldn't just do this directly...
[1, 5, 10]
Well, you can do something like this.
%i(1 2 3).map(&:to_s).map { |i| Integer(i) } #=> [1, 2, 3]
Using a range seems like it might be the easiest:
[26] pry(main)> (1..3).to_a
=> [1, 2, 3]

How can I initiate a list with a list element in julia?

I want to make a list of list in julia. It should be like this:
a = [1,"char", [1, 2, 3]]
a[3]
# ouput should be [1,2,3]
However, julia automatically does concatenation, so it ends up to be [1, "char", 1, 2, 3]
How can I do such things in julia without initiating the list with another value and then assigning a list to it like:
a = [1, "char", 3]
a[3] = [1, 2, 3]
julia> a = Any[1,"char", [1, 2, 3]]
3-element Array{Any,1}:
1
"char"
[1,2,3]
The style of array concatenation have been changes, now to concat arrays, the right syntax is: a = [1;"char"; [1, 2, 3]], so [1;"char"; [1, 2, 3]]==Any[1;"char"; [1, 2, 3]] # => true but when Julia faces [1,"char", [1, 2, 3]] by default it tries to concat possible element types.

Resources