开发者

can't convert Array into Integer

I'm trying to iterate through an array, @chem_species = ["H2", "S", "O4"] and multiply a constant times the amount of constants present: H = 1.01 * 2, S = 32.1 * 1 and so on. The constants are of course defined within the class, before the instance method.

The code I've constructed to do this does not function:

def fw
x = @chem_species.map { |chem| chem.scan(/[A-Z]/)}
y = @chem_species.map { |chem| chem.scan({/\d+/)}
@mm = x[0] * y[0] 
end

yields -> TypeError: can't convert Array into Integer

Any suggestions on 开发者_运维知识库how to better code this? Thank you for your insight in advance.


How about doing it all in one scan & map? The String#scan method always returns an array of the strings it matched. Look at this:

irb> "H2".scan /[A-Z]+|\d+/i
  => ["H", "2"]

So just apply that to all of your @chem_species using map:

irb> @chem_species.map! { |chem| chem.scan /[A-Z]+|\d+/i }
  => [["H", "2"], ["S"], ["O", "4"]]

OK, now map over @chem_species, converting each element symbol to the value of its constant, and each coefficient to an integer:

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]

There's your molar masses!

By the way, I suggest you look up the molar masses in a single hash constant instead of multiple constants for each element. Like this:

MASSES = { :H => 1.01, :S => 32.01, :O => 15.99 }

Then that last map would go like:

@chem_species.map { |(elem, coeff)| MASSES[elem.to_sym] * (coeff || 1).to_i }


You have a syntax error in your code: Maybe it should be:

def fw
x = @chem_species.map { |chem| chem.scan(/[A-Z]/)}
y = @chem_species.map { |chem| chem.scan(/\d+/)}
@mm = x[0] * y[0] 
end


Have you looked at the output of @chem_species.map { |chem| chem.scan(/[A-Z]/)} (or the second one for that matter)? It's giving you an array of arrays, so if you really wanted to stick with this approach you'd have to do x[0][0].

Instead of mapping, do each

@chem_species.each { |c| c.scan(/[A-Z]/) }

Edit: just realized that that didn't work at all how I had thought it did, my apologies on a silly answer :P


Here's a way to multiply the values once you have them. The * operator won't work on arrays.

x = [ 4, 5, 6 ]
y = [ 7, 8, 9 ]
res = []
x.zip(y) { |a,b| res.push(a*b) }
res.inject(0) { |sum, v| sum += v}
# sum => 122

Or, cutting out the middle man:

x = [ 4, 5, 6 ]
y = [ 7, 8, 9 ]
res = 0
x.zip(y) { |a,b| res += (a*b) }
# res => 122


(one-liners alert, off-topic alert)

you can parse the formula directly:

"H2SO4".scan(/([A-Z][a-z]*)(\d*)/)
# -> [["H", "2"], ["S", ""], ["O", "4"]]

calculate partial sums:

aw = { 'H' => 1.01, 'S' => 32.07, 'O' => 16.00 }
"H2SO4".scan(/([A-Z][a-z]*)(\d*)/).collect{|e,x| aw[e] * (x==""?1:x).to_i}
# -> [2.02, 32.07, 64.0]

total sum:

"H2SO4".scan(/([A-Z][a-z]*)(\d*)/).collect{|e,x| aw[e] * (x==""?1:x).to_i}.inject{|s,x| s+x}
# -> 98.09
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜