Как насчет того, чтобы сделать все это за одно сканирование и карту?Метод String#scan
всегда возвращает массив строк, которым он соответствует.Посмотрите на это:
irb> "H2".scan /[A-Z]+|\d+/i
=> ["H", "2"]
Так что просто примените это ко всем вашим @chem_species
, используя map
:
irb> @chem_species.map! { |chem| chem.scan /[A-Z]+|\d+/i }
=> [["H", "2"], ["S"], ["O", "4"]]
ОК, теперь сопоставьте с @chem_species
, преобразовав каждый элементсимвол к значению его константы, а каждый коэффициент к целому числу:
irb> H = 1.01
irb> S = 32.01
irb> O = 15.99
irb> @chem_species.map { |(elem, coeff)| self.class.const_get(elem) * (coeff || 1).to_i }
=> [2.02, 32.01, 63.96]
Там ваши молярные массы!
Кстати, я предлагаю вам посмотреть молярные массы в одномхеш-константа вместо нескольких констант для каждого элемента.Вот так:
MASSES = { :H => 1.01, :S => 32.01, :O => 15.99 }
Тогда последняя карта будет выглядеть так:
@chem_species.map { |(elem, coeff)| MASSES[elem.to_sym] * (coeff || 1).to_i }