Combinations of consecutive elements of an array - ruby

Is there any builtin method to produce combinations of consecutive array elements?
a = ['1','2','3','4']
# => '12','23','34'
I tried the methods permutation, combination, and each_slice, but was not able to produce required output.
a.permutation(2).to_a #=> [[1,2],[1,3],[1,4],[2,1],[2,3],[2,4],[3,1],[3,2],[3,4]]
a.combination(2).to_a #=> [[1,2],[1,3],[1,4],[2,3],[2,4],[3,4]]
a.each_slice(2) {|a| p a} #=> ["1", "2"],["3", "4"]

No, but you can do it with a combination of a few methods.
a.each_cons(2).map(&:join)
# => ["12", "23", "34"]

Related

Inverting a hash value (that's an array) into new individual keys

I have the following:
lumpy_hash = { 1 => ["A", "B"] }
then if I invoke Hash#invert on this hash, I'd like to get:
lumpy_hash = {"A" => 1, "B" => 1}
I don't get that from using Hash#invert. Any ideas on doing this? I'm not sure if I should try Hash#map or Hash#invert.
There are many ways to do this. Here is one:
Hash[lumpy_hash.map { |k,v| v.product([k]) }.first]
#=> {"A"=>1, "B"=>1}
I don't think the method Hash#invert is useful here.
The steps:
enum = lumpy_hash.map
#=> #<Enumerator: {1=>["A", "B"]}:map>
k,v = enum.next
#=> [1, ["A", "B"]]
k #=> 1
v #=> ["A", "B"]
a = v.product([k])
#=> ["A", "B"].product([1])
#=> [["A", 1], ["B", 1]]
Hash[a]
#=> {"A"=>1, "B"=>1}
Here's another way that makes use of a hash's default value. This one is rather interesting:
key,value = lumpy_hash.to_a.first
#=> [1, ["A","B"]]
Hash.new { |h,k| h[k]=key }.tap { |h| h.values_at(*value) }
#=> {"A"=>1,"B"=>1}
Object#tap passes an empty hash to its block, assigning it to the block variable h. The block returns h after adding three key-value pairs, each having a value equal to the hash's default value. It adds the pairs merely by computing the values of keys the hash doesn't have!
Here's another, more pedestrian, method:
lumpy_hash.flat_map{|k,vs| vs.map{|v| {v => k}}}.reduce(&:merge)
=> {"A"=>1, "B"=>1}

Simple ruby array smallest integer?

This is my array : array = ["1", "Hel", "6", "3", "lo" ]I want to output the smallest number in the array. Then I want to output the largest number in the array? How do I achieve this? Thanks!
Well it depends how you want to handle the string elements that aren't easily parsed into numbers. Like "Hel" and "lo".
If you do this:
array.map {|x| Integer(x) rescue nil }.compact.min
array.map {|x| Integer(x) rescue nil }.compact.max
Then you'll ignore those, which is probably the right thing, assuming you don't have some reason for considering "Hel" and "lo" to have numerical values.
numbers = array.select { |x| x[/^-?\d+$/] }.map(&:to_i)
# => [1, 6, 3]
numbers.min
# => 1
numbers.max
# => 6
Another variation to work with negative numbers
smalles, largest =
["1", "Hel", "6", "3", "lo","-9" ].select { |x| x[/^-?\d+$/] }.minmax_by(&:to_i)
smallest # => -9 largest # => 6
smallest, largest =
["1", "Hel", "6", "3", "lo" ].reject{|s| s =~ /\D/}.minmax_by(&:to_i)
smallest # => "1"
largest # => "6"
Another way:
array.join(',').scan(/-?\d+/).minmax_by(&:to_i)
#=> ["-4", "6"]
we can use unicode [[:digit:]] instead writing regular expression as
array.join(',').scan(/[[:digit:]]/).minmax_by(&:to_i)

How to convert Fixnum to Integer in ruby

I am trying to get Integers, but i am getting 'Fixnum' values.
For Eg:
arr = ["1", "2", "3", "4"]
arr.each do |a|
m = a.to_i
m.class.name
Result
=> Fixnum
According to the above example, how can i get Integer values?
Fixnum is a Integer only but while implementing one plugin, it will through an error like 'Please enter only integer'.
In Ruby integers are either of the class Fixnum or Bignum for bigger numbers. Both of them inherit from the Integer class.
So you already got an integer, no need to convert it further.
1.class #=> Fixnum
1.class.superclass #=> Integer
To convert the array elements to integers you would do this:
arr = ["1", "2", "3", "4"]
arr.map(&:to_i) #=> [1, 2, 3, 4]
Fixnum is the ruby class for standard integers.
Well to be specific, the Integer class covers both Fixnums and Bignums, but in all honesty there's nothing to done here.
All Fixnum(s) are already Integer. Here is some sample:
"12".to_i.class
#=> Fixnum
"12".to_i.integer?
#=> true
"12".to_i.to_int
#=> 12
The above all is possible as-
"12".to_i.class.superclass
#=> Integer

Array of Strings to Convert to Mixed Array

I'm trying to convert an Array of Arrays consisting of Ruby Strings into an Array of Arrays consisting of Strings and Floats.
Here is my attempt:
array = [["My", "2"], ["Cute"], ["Dog", "4"]]
array.collect! do |x|
x.each do |y|
if y.gsub!(/\d+/){|s|s.to_f}
end
end
end
=> [["My", "2.0"], ["Cute"], ["Dog", "4.0"]]
I'm looking for this to rather return [["My", 2.0], ["Cute"], ["Dog", 4.0]] What did I do wrong?
What you did wrong is that you used gsub!. That takes a string and changes the string. It doesn't turn it into anything else, no matter what you do (even if you convert it to a float in the middle).
A simple way to achieve what you want is:
[["My", "2"], ["Cute"], ["Dog", "4"]].map{|s1, s2| [s1, *(s2.to_f if s2)]}
If you do not want to create the element array, but replace its contents, then:
[["My", "2"], ["Cute"], ["Dog", "4"]].each{|a| a[1] = a[1].to_f if a[1]}
If the numerical strings appear in random positions, then:
[["My", "2"], ["Cute"], ["Dog", "4"]]
.each{|a| a.each.with_index{|e, i| a[i] = a[i].to_f if a[i] and a[i] =~ /\d+/}}

How can I get a list from a Ruby enumerable?

I know of Python's list method that can consume all elements from a generator. Is there something like that available in Ruby?
I know of :
elements = []
enumerable.each {|i| elements << i}
I also know of the inject alternative. Is there some ready available method?
Enumerable#to_a
If you want to do some transformation on all the elements in your enumerable, the #collect (a.k.a. #map) method would be helpful:
elements = enumerable.collect { |item| item.to_s }
In this example, elements will contain all the elements that are in enumerable, but with each of them translated to a string. E.g.
enumerable = [1, 2, 3]
elements = enumerable.collect { |number| number.to_s }
In this case, elements would be ['1', '2', '3'].
Here is some output from irb illustrating the difference between each and collect:
irb(main):001:0> enumerable = [1, 2, 3]
=> [1, 2, 3]
irb(main):002:0> elements = enumerable.each { |number| number.to_s }
=> [1, 2, 3]
irb(main):003:0> elements
=> [1, 2, 3]
irb(main):004:0> elements = enumerable.collect { |number| number.to_s }
=> ["1", "2", "3"]
irb(main):005:0> elements
=> ["1", "2", "3"]

Resources