views:

33

answers:

3

I have the following method:

def speciate 
  chem_formula.each { |chemical|
    @chem_species = chemical.scan(/[A-Z][^A-Z]*/)
    puts @chem_species
  }
end

that produces:

H2
S
O4

@chem_species = ["S", "O4"]

from: @chem_formula = ["H2" "SO4"]

How do you set the array to include all iterations? That is how do you output ["H2", "S", "O4"] rather than ["S", "O4"] Thank you in advance.

+1  A: 

Not the most elegant as you're building an array then flattening but this works:

@chem_formula.map{|chem| chem.scan(/[A-Z][^A-Z]*/) }.flatten
brad
I have to disagree, this *is* elegant :)
Leventix
i say not so elegant as there are multiple array iterations going on here under the hood. While yes, it's one line and *looks* very pretty and elegant, I think too many Ruby developers forgot that these Ruby array functions .each, .map etc... all iterate over arrays, making them comparatively slow to a custom built algorithm. ie. this could certainly be achieved with a few lines of code and a SINGLE iteration.
brad
A: 
def speciate
  @chem_species = []
  chem_formula.each { |chemical|
    @chem_species.concat(chemical.scan(/[A-Z][^A-Z]*/))
    puts @chem_species
  }
end
sepp2k
A: 

An elegant way is:

@chem_formula.flat_map{|chem| chem.scan(/[A-Z][^A-Z]*/) }

Note: flat_map is new to Ruby 1.9.2. Either ugrade, require 'backports' or use map{}.flatten if using an older Ruby.

Marc-André Lafortune