hinekure.net が http://hspdev-wiki.net/ から自動クローリングした結果を表示しています。画像やリソースなどのリンクが切れています。予めご了承ください。
連想配列 - HSP開発wiki
トップ    編集凍結 差分バックアップ添付複製名前変更リロード   新規一覧単語検索最終更新   最終更新のRSS

ラボ
***作成中***

written by araran

連想配列とは

連想配列とは添え字に自然数を利用する配列に対し、任意の文字列を添え字として使う配列を挿します。

  • 通常の配列
    array.0 = "95点" ; 代入
    result = array.0 ; 取得
  • 連想配列
    array[国語] = "95点" ; 代入
    result = array[国語] ; 取得

HSPでは3で連想配列を言語仕様として導入予定なので今回は2.61をベースに連想配列の実装を考えてみたいと思います。
(私がまだeEasy3Dに合わせ3に手を出していないのも理由w)
HSP3でWindowsのScriptランタイム(JScript,VBScript)を利用する内容はこちら→COMDictionary
このページではHSPによる実装を考えます。

簡単な実装

パフォーマンスを考慮せず、上記の機能のみを提供する最小の例

filemap[1.2].as
Everything is expanded.Everything is shortened.
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
-
|
|
!
-
|
|
|
!
-
|
|
!
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
-
|
|
!
-
|
|
!
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
/******************************************************************************
 *                                                                            *
 *                            データ構造:連想配列1                           *
 *                                                                            *
 ******************************************************************************/
 
    #module "map"
 
    ;-----------------------------------------------------------------------
    ; 連想配列を作成する
    ; map_dim 要素数, keyの最大レングス, valueの最大レングス
    ;-----------------------------------------------------------------------
    #deffunc map_dim int, int, int
//      モジュール内でグローバルな変数は別途用意しなければならない < kz3
//      mref mapSize, 0
//      mref keyLength, 1
//      mref valueLength, 2
        mref n1, 0 : mapSize     = n1 ; 要素数
        mref n2, 1 : keyLength   = n2 ; keyの最大レングス
        mref n3, 2 : valueLength = n3 ; valueの最大レングス
 
        sdim keyArray, keyLength, mapSize
        sdim valueArray, valueLength, mapSize
        return
 
    ;-----------------------------------------------------------------------
    ; 指定の値と指定されたキーをこのマップに関連付けます。
    ; マップが以前にこのキーのマッピングを保持していた場合、古い値が置き換えられます。
    ; map_put key, value
    ;-----------------------------------------------------------------------
    #deffunc map_put str, str
        mref return_status,64 ; statusの戻り値
        mref key, 32          ; key
        mref value, 33        ; value
 
//      1つ余計にループを回して最終回チェック
//      さらに最終回チェックは要素の参照前にチェック < kz3
//      repeat mapSize      
        repeat mapSize+1
          if cnt == mapSize {       ;cntが配列の要素数に達した=空きがない。
            return_status = 1
            break
          }
          if keyArray.cnt == "" {   ;key配列が空なら追加
            keyArray.cnt = key
            valueArray.cnt = value
            break
          }
          if keyArray.cnt == key {  ;key配列に同じ値が見つかればvalueを更新
            valueArray.cnt = value
            break
          }
 
        loop
        
        return
 
    ;-----------------------------------------------------------------------
    ; キーにマップされている値を返します。
    ; 存在しなければstatus=0が返ります。
    ; map_get key, 結果を保持する変数
    ;-----------------------------------------------------------------------
    #deffunc map_get str, val
        mref return_status,64 ; statusの戻り値
        mref get_key, 32      ; key
        mref get_value, 25    ; 戻り値
 
//      1つ余計にループを回して最終回チェック
//      さらに最終回チェックは要素の参照前にチェック < kz3
//      repeat mapSize
        repeat mapSize + 1
          if cnt == mapSize {           ;cntが配列の要素数に達した=空きがない。
            return_status = 1
            break
          }
          if keyArray.cnt == get_key {  ;key配列に同じ値が見つかればvalueを更新
            get_value = valueArray.cnt
            break
          }
 
        loop
        
        return
    #global
 
/* -------------------------------------------------------------------------- *
 *                                                                            *
 *                           S A M P L E                           *
 *                                                                            *
 * -------------------------------------------------------------------------- */
    map_dim 10, 10, 100   ; 連想配列の作成
 
    map_put "国語", "90点"
 
    sdim result
    map_get "国語", result
    
    if stat!1 : print result : else : print "見つかりません."
 
    stop
  • 複数個の連想配列が作れない。
  • 引数を(文字列or文字配列変数)にするにはどうしたら良いのでしょう? <-本当にHSP知らない。この人w
    • こういうことかな?mref命令ページ作りました。 -- kz3
    • ぐふぉ、記述を間違ってました。
      sdim a
      a="aa"
      test a
      test "bb"
      のどちらでもOKなのは可能でしょうか?
  • ちっとHSP3を調べて見ました。
    mref命令なしで出来るのは魅力。でも「var」と「str」で分かれてるあたりがピンときません。
    あとモジュール変数と言う形で、上記のようなものを複数インスタンスできるのも大きな魅力。
    さらに配列が動的拡張になっているも魅力。次に出てくるハッシュテーブルの実装には適している感じですね。

上のソースを元にHSP3用にして見ました。
map2.0 for hsp3 .hsp

同じくモジュール変数使用版
map2.12_for_hsp3 .hsp

ハッシュ関数の実装1

ハッシュコード(ハッシュ値)と言われる要約値をを求める要約関数のことをハッシュ関数といいます。
通常、一方向要約関数です。つまり文字列からハッシュコードは求められるが、
ハッシュコードからは元の文字列を求めることは出来ません。
このハッシュコード、ハッシュ関数は様々なところで利用されています。

  • 通信内容にハッシュコードを付与することで、通信内容の保証
  • 暗号化などのセキュリティにおける内容の保証
  • 簡易文字比較
  • ハッシュテーブルの作成

ハッシュ関数には様々な実装があります。有名なものとしてはMD5などがあり、認証やデジタル署名などにも利用されます。
MD5は非常に高機能で、似たような文章であっても一文字違うだけで、まったく異なるコードを返します。

今回は、わかりやすい簡単な実装を考えてみます。
辞書のインデックスをイメージしてください。
国語辞典なら「あいうえお・・・・」
英語辞典なら「abcdefg・・・・」
漢字字典なら「1画、2画、3画・・・」
などのインデックスです。
同様に、文字列の最初の一文字がA〜Zのでどれかでハッシングするハッシュ関数の実装を考えます。

「Hot」⇒h
「Soup」⇒s
「Processor」⇒p

が求まる実装です。

サンプルコード


ハッシュ関数の実装2 実用編

上記の例では、文字列がアルファベットのみの場合、26種類のハッシュコードを求めるのに固定されてしまいます。
また、先頭文字に同じ文字を利用する場合などに機能しません。

そこでピット演算を利用した簡単で、実用的な実装を考えてみたいと思います。

サンプルコード

ハッシングを用いた連想配列の高速化〈ハッシュテーブル〉

さて本題です。通常、連想配列はハッシュ関数を利用したハッシュテーブルとして実装されます。
これはパフォーマンスを向上させます。これによりしばしば通常の配列ではなく連想配列を利用する要因となります。

ハッシュテーブルとはハッシュコードごとに、「簡単な実装」で作成したような配列を管理するのです。
「ハッシュ関数の実装1」で実装したハッシュ関数を利用した場合、まさに辞書と同じ体系でデータを管理することになります。
この為、全体を検索するより効率的にデータを検索できる訳です。

サンプルコード

問題点。

HSP2.61では動的配列の拡張は出来ません。
その為、26個のハッシュコードに対し、10個づづの配列を作成したとしても、260個の変数を作成することになります。
これは運がよければ260個の変数を格納できますが、運が悪いと11個の変数を格納した時点でエラーとなってしまいます。
回避する方法としては、10個が埋まった時点で、10個を別の配列に退避し、再度、20個ノ配列を確保するなど、自前で配列を拡張することになります。

ハッシングを用いた連想配列の高速化〈リングバッファ〉

動的配列の拡張が出来ないHSP向けに同じところに同じハッシュコードを持つデータが集まる実装。

コメント

  • araranさん・・・ NEOZC PROJECT 頑張ってください!こっちは ぼっ僕が頑張ります!(ぇ
    ところでmap_getの指定したキーが見つからなかったところでエラーがあったので直しておきます^^; -- kz3 2005-10-05 15:59:40 (水)
  • というかmapSizeがとんでもない値になってます@@; -- kz3 2005-10-05 16:13:01 (水)
  • なんかstr型指定に問題ありなようですよ?int型のパラメータが面白いことに引数は先頭から・・・あぅ・・・ちょっと急用が出来てしまったので話はまた今度(!? -- kz3 2005-10-05 16:36:44 (水)
  • すみませぬ。忘れてるわけでは無いのですが、手が回ってません。テストしたつもりですが・・怪しいw -- araran 2005-10-06 09:45:46 (木)
  • 簡単な実装編に手を加えました。これで大丈夫なはずです! -- kz3 2005-10-06 09:46:53 (木)
  • hspって変数に日本語が使えるんですけど、それを利用できないでしょうか? -- 今地区所? 2012-01-19 (木) 00:14:41

URL B I U SIZE Black Maroon Green Olive Navy Purple Teal Gray Silver Red Lime Yellow Blue Fuchsia Aqua White

トップ    編集凍結 差分バックアップ添付複製名前変更リロード   新規一覧単語検索最終更新   最終更新のRSS
Last-modified: 2012-01-19 (木) 00:15:04 (689d)