ハッシュ実装
連想配列と言う言葉をご存知だろうか。Perl使いにはハッシュの名でお馴染みの概念で、吉里吉里使いも知っているのではないだろうか。
この連想配列を、速度は度外視してNScripterで実装してみた。文字列変数を一つ使って、それに文字列でも数値でもキーと結びつけて格納できるようにした。
スクリプトはこんな感じである。
*define defsub hash_read ; 指定したハッシュから値を読み出す。 defsub hash_exist ; 指定したハッシュに指定したキーが存在するかどうか。 defsub hash_mov ; 指定したハッシュに値を書き込む defsub hash_write ; hash_movのエイリアス defsub hash_delete ; 指定したハッシュからそのキーを消去する。 defsub hash_mov_fast ; 指定したキーが存在しない場合の高速書き込み defsub hash_write_fast ; hash_mov_fastのエイリアス defsub hash_read2 ; 得られた値を数値にして返す。 defsub hash_mov2 ; 数値を書き込む。 defsub hash_write2 ; hash_mov2のエイリアス defsub hash_mov_fast2 ; 数値を高速に書き込む。 defsub hash_write_fast2 ; hash_mov_fast2のエイリアス numalias hash_num,100 numalias hash_key,101 numalias hash_result,102 numalias hash_len,103 numalias hash_key_len,104 numalias hash_temp,105 numalias hash_loop,106 numalias hash_exist_result,107 numalias hash_value,108 numalias hash_delete_flag,109 numalias hash_result2,110 stralias hash_separater,"&" stralias hash_separater2,"=" game *hash_read2 getparam i%hash_result2,s%hash_num,$hash_key ; 結果格納変数・対象文字列変数・読み出すハッシュキー hash_read $hash_result2,$%hash_num,$hash_key atoi %%hash_result2,$hash_result2 return *hash_read getparam s%hash_result,s%hash_num,$hash_key ; 結果格納変数・対象文字列変数・読み出すハッシュキー mov $%hash_result,"" ; 結果の初期化 hash_exist %hash_temp,$%hash_num,$hash_key ; そのキーがあるかどうかチェックする。 if %hash_temp<0 return ; 存在しないなら、空白を返す。 mov %hash_loop,%hash_key_len *hash_read_loop inc %hash_loop mid $hash_temp,$%hash_num,%hash_temp+%hash_loop,1 notif $hash_temp=hash_separater goto *hash_read_loop mid $hash_temp,$%hash_num,%hash_temp+1,%hash_loop-1 split $hash_temp,hash_separater2,$hash_temp,$%hash_result return ; 指定したハッシュに指定したキーが存在するかどうか。 ; 返り値が-1なら、存在しない。それ以外なら何文字目かが入る。 *hash_exist getparam i%hash_exist_result,s%hash_num,$hash_key ; 結果格納変数・対象文字列変数・調査するハッシュキー mov %%hash_exist_result,-1 ; 結果の初期化 len %hash_len,$%hash_num if %hash_len=0 return ; ハッシュが初期化されているなら、すぐに戻る。 len %hash_key_len,$hash_key if %hash_key_len=0 return ; 空白のキーはバグの元なのでちょっと……。 for %hash_loop=0 to %hash_len-%hash_key_len+1 mid $hash_temp,$%hash_num,%hash_loop,1 ; 一文字取得 notif $hash_temp=hash_separater jumpf ; それが&でなければ次のループ mid $hash_temp,$%hash_num,%hash_loop+1,%hash_key_len+1 ; その後のキーを取得。 notif $hash_temp=$hash_key+hash_separater2 jumpf ; それがキー名+=でなければ次のループ ; ヒットした。 mov %%hash_exist_result,%hash_loop+1 break ~ next return *hash_mov2 *hash_write2 getparam s%hash_num,$hash_key,%hash_value ; 対象の文字列変数・キー・新しい値 itoa $hash_value,%hash_value goto *hash_mov_body *hash_mov *hash_write getparam s%hash_num,$hash_key,$hash_value ; 対象の文字列変数・キー・新しい値 *hash_mov_body mov %hash_delete_flag,0 if $%hash_num="" mov $%hash_num,hash_separater hash_exist %hash_temp,$%hash_num,$hash_key ; そのキーがあるかどうかチェックする。 if %hash_temp<0 goto *hash_mov_last *hash_delete_body ; 既存のキーがあるとちょっと面倒かな……。 mid $hash_temp,$%hash_num,0,%hash_temp-1 mov $hash_result,$hash_temp *hash_write_loop inc %hash_temp mid $hash_temp,$%hash_num,%hash_temp,1 notif $hash_temp=hash_separater goto *hash_write_loop mid $hash_temp,$%hash_num,%hash_temp,%hash_len-%hash_temp add $hash_result,$hash_temp mov $%hash_num,$hash_result ; 文字列変数の最後に追加する。 *hash_mov_last if %hash_delete_flag=0 add $%hash_num,$hash_key+hash_separater2+$hash_value+hash_separater mov %hash_delete_flag,0 return *hash_write_fast2 *hash_mov_fast2 getparam s%hash_num,$hash_key,%hash_value ; 対象の文字列変数・キー・新しい値 itoa $hash_value,%hash_value goto *hash_move_last *hash_write_fast *hash_mov_fast getparam s%hash_num,$hash_key,$hash_value ; 対象の文字列変数・キー・新しい値 goto *hash_move_last *hash_delete getparam s%hash_num,$hash_key if $%hash_num="" mov $%hash_num,hash_separater hash_exist %hash_temp,$%hash_num,$hash_key ; そのキーがあるかどうかチェックする。 if %hash_temp<0 return ; キーがなければ何もしない。 mov %hash_delete_flag,1 ; フラグを立てる。 goto *hash_delete_body *start end
一つの文字列変数に対し、hash_readやhash_writeを通じてキーを添えてアクセスすることで、不特定多数の数値や文字列を一つの文字列変数に収めることができる。
意味がわかったら使ってみて欲しい。