1

我有密码...

var userArray=userIn.match(/(?:[A-Z][a-z]*|\d+|[()])/g);

...将用户输入的化学式分离为其组成部分。

例如,输入Cu(NO3)2N3将产生

Cu , ( , N , O , 3 , ) , 2 , N , 3。

在查找每个元素在整个重量中的百分比时,我需要计算每个元素输入了多少次。

所以在上面的例子中,

Cu : 1 , 
N  : 5 , 
O : 6 

关于我应该如何做这件事的任何建议?

4

2 回答 2

2

您需要构建一个解析器

没有简单的解决方法。您需要嵌套和内存,正则表达式无法很好地处理(好吧,真正的CS 正则表达式根本无法处理)。

首先,你得到你所拥有的结果正则表达式。这称为标记化

现在,您必须实际解析它。

我建议以下方法我会给你伪代码,因为我认为它会更好地演绎。如果您对此有任何疑问,请告诉我:

方法chemistryExpression ( tokens ): #Tokens 是你的正则表达式的结果

  1. 创建一个名为map的空地图

  2. 当下一个标记是一个字母时,使用它(从标记中删除它)

    2.1 将出现次数为 1 的字母添加到地图中,如果它已经在地图中,则将其加一

  3. 如果下一个令牌是(,则使用它: # 处理嵌套

    3.1 将parseExpression (tokens) 中的出现添加到地图中(注意,tokens 已更改)

    3.2 去掉)刚刚遇到的多余的

  4. num = 消费令牌,而下一个令牌是数字并转换为 int

  5. 将地图中所有标记的出现次数乘以num

  6. 归还地图

实施建议

  • 地图可以只是一个对象。

    • 添加到地图是检查键是否存在,如果不存在,则将其设置为 1,如果存在,则将其值加一。

    • 乘法可以使用for... in循环来完成。

  • 该解决方案是递归的,这意味着您在这种情况下使用了一个调用自身的函数(chemistryExpression)。该解析器是递归下降解析器的一个非常基本的示例,并且可以很好地处理嵌套。

  • 常识和良好实践需要两种方法

    • peek - 令牌中的下一个令牌是什么,这是tokens[0]
    • next - 从令牌中获取下一个令牌,这是tokens.unshift()
于 2013-06-28T23:03:47.707 回答
0

对于 userArray 中的每个值,检查是否有下一个元素 anf 是否下一个元素是数字,如果是,则将此数字添加到当前元素类型的计数中,否则添加 1。您可以将对象用作映射到存储每个不同元素类型的计数:

var map = { }
map[userArray[/*an element*/] = ...

编辑:如果你的数字比一个数字长,那么在一个循环中,而下一个是一个数字,将所有数字连接成一个字符串和 parseInt()

于 2013-06-28T23:01:02.437 回答