RadW2020
RadW2020

Reputation: 148

How to "sum" enumerables in Ruby

Is it possible to "sum" diverse enumerables when they are string mode? per example like this? (well, I know this doesn't work.)

(( 'a'..'z') + ('A'..'Z')).to_a

note: I am asking about getting an array of string chars from a to z and from A to Z all together. About string mode I mean that the chars will appears like ["a", "b", ..... , "Y", "Z"]

Upvotes: 1

Views: 170

Answers (6)

Arup Rakshit
Arup Rakshit

Reputation: 118271

About string mode I mean that the chars will appears like ["a", "b", ..... , "Y", "Z"]

To answer the above:

Array('a'..'z').concat Array('A'..'Z')

Upvotes: 0

Yevgeniy Anfilofyev
Yevgeniy Anfilofyev

Reputation: 4847

Not answer but benchmarking of answers:

require 'benchmark'

n = 100000
Benchmark.bm do |x|
  x.report("flat_map   : ") { n.times do ; [('A'..'Z'), ('a'..'z')].flat_map(&:to_a) ; end }
  x.report("map.flatten: ") { n.times do ; [('A'..'Z'), ('a'..'z')].map(&:to_a).flatten ; end }
  x.report("splat      : ") { n.times do ; [*('A'..'Z'), *( 'a'..'z')] ; end }
  x.report("concat arr : ") { n.times do ; ('A'..'Z').to_a + ('a'..'z').to_a  ; end }
end

Result:

#=>       user     system      total        real
#=> flat_map   :   0.858000   0.000000   0.858000 (  0.883630)
#=> map.flatten:   1.170000   0.016000   1.186000 (  1.200421)
#=> splat      :   0.858000   0.000000   0.858000 (  0.857728)
#=> concat arr :   0.812000   0.000000   0.812000 (  0.822861)

Upvotes: 2

spickermann
spickermann

Reputation: 106912

Like this?

[('a'..'z'), ('A'..'Z')].map(&:to_a).flatten

Or this?

('a'..'z').to_a + ('A'..'Z').to_a

Upvotes: 4

Darkmouse
Darkmouse

Reputation: 1939

['a'..'z'].concat(['A'..'Z'])

This is probably the quickest way to do this.

Upvotes: 0

Jörg W Mittag
Jörg W Mittag

Reputation: 369468

Since you want the elements from the first Range to be at the end of the output Array and the elements of the last Range to be at the beginning of the output Array, but still keep the same order within each Range, I would do it like this (which also generalizes nicely to more than two Enumerables):

def backwards_concat(*enums)
  enums.reverse.map(&:to_a).inject([], &:concat)
end

backwards_concat('A'..'Z', 'a'..'z')

Upvotes: 0

Doguita
Doguita

Reputation: 15703

You can use the splat operator:

[*('A'..'Z'), *( 'a'..'z')]

Upvotes: 9

Related Questions