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 正規表現ではまったく処理できません)。

まず、結果の正規表現を取得します。これはトークン化と呼ばれます。

さて、実際にそれを解析する必要があります。

次のアプローチをお勧めします。疑似コードを提供します。演繹的に優れていると思うからです。ご不明な点がございましたら、お気軽にお問い合わせください。

method chemistryExpression ( tokens ): #Tokens は正規表現の結果です

  1. mapという名前の空のマップを作成します

  2. 次のトークンが文字である間、それを消費します (トークンから削除します)。

    2.1 オカレンス 1 で文字をマップに追加するか、既にマップ内にある場合は 1 ずつ増やします

  3. 次のトークンが の場合、(それを消費します。

    3.1 parseExpression (トークン) からのオカレンスをマップに追加します (注意、トークンが変更されました)

    3.2 見つけた余分なものを削除)する

  4. num = 次のトークンが数値である間にトークンを消費し、int に変換します

  5. マップ内のすべてのトークンの出現回数にnumを掛けます

  6. 地図を返す

実装提案

  • マップは単なるオブジェクトにすることができます。

    • マップに追加すると、キーが存在するかどうかがチェックされます。存在しない場合は 1 に設定し、存在する場合は値を 1 増やします。

    • for... in乗算はループを使用して実行できます。

  • このソリューションは再帰的です。つまり、この場合、自分自身を呼び出す関数 (chemistryExpression) を使用していることを意味します。このパーサーは、再帰降下パーサーの非常に基本的な例であり、ネストを適切に処理します。

  • 常識と優れた実践には 2 つの方法が必要です

    • peek - トークンの次のトークンは何ですか。これはtokens[0]
    • next - トークンから次のトークンを取得します。これはtokens.unshift()
于 2013-06-28T23:03:47.707 に答える
0

userArray の各値について、次の要素があるかどうかを確認し、その次の要素が数値である場合は、この数値を現在の要素タイプのカウントに追加し、そうでない場合は 1 を追加します。 オブジェクトをマップとして使用して、異なる要素タイプごとにカウントを保存します。

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

EDIT : 数字が 1 桁より長い場合は、次が数字である間にループして、すべての数字を文字列に連結し、parseInt()

于 2013-06-28T23:01:02.437 に答える