奈良阪某/YAYAで連想配列
をテンプレートにして作成
[
トップ
] [
新規
|
一覧
|
検索
|
最終更新
|
ヘルプ
]
開始行:
YAYAで連想配列が使えないと聞いたので簡単なのを実装してみ...
どれが速いかわからないので数種類やってみた。
#contents
- バグがあったら報告してください。
- ライセンスは一応CC0とかで。
* ハッシュ:1つの連想配列メモリを使ってIDで区別する実装(微...
EVALと巨大な引数渡しを回避する方法
** 利点 [#qe980da8]
- EVAL等の遅そうな処理がない
** 欠点 [#g703bee3]
- 実行時全体のハッシュが一堂に会するので、要素数が多くな...
- EVAL等がない代わりにロジックは煩雑
- YAYAが変数を自動保存するので終了時に内部変数を削除しな...
- 操作関数の返り値を返さないのが面倒
** 使用例 [#m0cff258]
// map__hash_size = 65536 // 確保するハッシュ領域のサイ...
_m = map_new() // 初期化してIDを取得
_junk = map_set(_m, 'key', 'value')
_k = map_get(_m, 'key')
_ks = map_keys(_m)
_junk = map_delete(_m, 'key')
_junk = map_destroy(_m) // 削除して使えるハッシュ領域を...
_junk = map_destroy_all() // ハッシュ領域のグローバル変...
** 実装 [#ua34a828]
/*
_map_id = map_new()
連想配列初期化
cf. map = {}
*/
map_new{
if ! ISVAR('map__hash_size') {
map__hash_size = 65536
}
if ! ISVAR('map__id_num') {
map__id_num = 0
}
if ! ISVAR('map__key_lists') {
map__key_lists = IARRAY
}
if ! ISVAR('map__keys') {
map__keys = IARRAY
}
if ! ISVAR('map__values') {
map__values = IARRAY
}
map__id_num
map__id_num++
}
/*
_value = map_set(_map_id, _key, _value)
連想配列_map_idの_keyに_valueをセット
cf. map{key} = value
*/
map_set{
_id = _argv[0]
_key = _argv[1]
_value = _argv[2]
_hash = map__get_only_index(_id, _key)
// キーが事前に存在しないならmap__key_listsにキー情報を...
if map__keys[_hash] == IVOID {
map__key_lists = (map__key_lists, _id, _key)
}
map__keys[_hash] = _key
map__values[_hash] = _value
_value
}
/*
_value = map_get(_map_id, _key)
連想配列_map_idの_keyを参照
cf. value = map{key}
*/
map_get{
_id = _argv[0]
_key = _argv[1]
_hash = map__get_only_index(_id, _key)
map__values[_hash]
}
/*
_junk = map_delete(_map_id, _key)
連想配列_map_idの_keyを削除
cf. delete(map{key})
*/
map_delete{
_id = _argv[0]
_key = _argv[1]
_hash = map__get_only_index(_id, _key)
map__keys[_hash] = IVOID
map__values[_hash] = IVOID
}
/*
_keys = map_keys(_map_id, _key)
連想配列_map_idの_keyを列挙
cf. keys = keys(map{key})
*/
map_keys{
_id = _argv[0]
_size = ARRAYSIZE(map__key_lists) / 2
_keys = IARRAY
for _i = 0; _i < _size; _i++ {
if map__key_lists[_i * 2] == _id {
_key = map__key_lists[_i * 2 + 1]
_hash = map__get_only_index(_id, _key)
if map__values[_hash] != IVOID {
_keys = (_keys, _key)
}
}
}
_keys
}
/*
_junk = map_destroy(_map_id)
連想配列_map_idを削除
*/
map_destroy{
// keysによりmap__keys, map__values当該を消してからmap_...
_id = _argv[0]
_keys = map_keys(_id)
foreach _keys; _key {
_hash = map__get_only_index(_id, _key)
map__keys[_hash] = IVOID
map__values[_hash] = IVOID
}
_size = ARRAYSIZE(map__key_lists) / 2
_to_delete = IARRAY
for _i = 0; _i < _size; _i++ {
if map__key_lists[_i * 2] == _id {
_to_delete = (_to_delete, _i)
}
}
_to_delete = ASORT('int,descending', _to_delete)
foreach _to_delete; _i {
map__key_lists[_i * 2, _i * 2 + 1] = IARRAY
}
}
/*
_junk = map_destroy_all()
連想配列が使用する変数を削除
*/
map_destroy_all{
ERASEVAR('map__hash_size', 'map__id_num', 'map__key_lis...
}
map__get_only_index{ // 重複しないようインデックスをずらす
_id = _argv[0]
_key = _argv[1]
_hash_key = _id + TOSTR(_key)
_hash = map__hash(_hash_key)
while (map__keys[_hash] != IVOID) && (map__keys[_hash] ...
if _hash >= (map__hash_size - 1){
_hash = 0
} else {
_hash++
}
}
_hash
}
map__hash{ // ハッシュ関数
_key = _argv[0]
_key_len = STRLEN(_key)
_hash = 0
for _i = 1; _i < _key_len; _i++ {
_hash = (_hash * 137 + CHRCODE(_key, _i)) % map__hash_...
}
_hash
}
* ハッシュ:EVALによる実装(あり?) [#y4e0d20d]
EVALを使う代わりにより自然なロジックで実装できる。
** 利点 [#bfa2dc6f]
- 自然なロジックで実装できる
** 欠点 [#r10a7b82]
- EVALが遅そう(実用上そう気になるレベルではない気がする)
- 変数の削除はやはり必要。
- 操作関数の返り値を返さないのが面倒
** 使用例 [#weff16ed]
// map__hash_size = 2048 // 一連想配列に確保するハッシュ...
_m = map_new() // 初期化してIDを取得
_junk = map_set(_m, 'key', 'value')
_k = map_get(_m, 'key')
_ks = map_keys(_m)
_junk = map_delete(_m, 'key')
_junk = map_destroy(_m) // 変数開放
** 実装 [#s09bacb2]
/*
_map_id = map_new()
連想配列初期化
cf. map = {}
*/
map_new{
if ! ISVAR('map__hash_size') {
map__hash_size = 2048
}
if ! ISVAR('map__id_num') {
map__id_num = 0
}
LETTONAME('map__keys_' + map__id_num, IARRAY)
LETTONAME('map__values_' + map__id_num, IARRAY)
map__id_num
map__id_num++
}
/*
_value = map_set(_map_id, _key, _value)
連想配列_map_idの_keyに_valueをセット
cf. map{key} = value
*/
map_set{
_id = _argv[0]
_key = _argv[1]
_value = _argv[2]
_hash = map__get_only_index(_id, _key)
_junk = EVAL('map__keys_' + map__id_num + '[_hash] = _k...
_junk = EVAL('map__values_' + map__id_num + '[_hash] = ...
_value
}
/*
_value = map_get(_map_id, _key)
連想配列_map_idの_keyを参照
cf. value = map{key}
*/
map_get{
_id = _argv[0]
_key = _argv[1]
_hash = map__get_only_index(_id, _key)
EVAL('map__values_' + map__id_num + '[_hash]')
}
/*
_junk = map_delete(_map_id, _key)
連想配列_map_idの_keyを削除
cf. delete(map{key})
*/
map_delete{
_id = _argv[0]
_key = _argv[1]
_hash = map__get_only_index(_id, _key)
_junk = EVAL('map__keys_' + map__id_num + '[_hash] = IV...
_junk = EVAL('map__values_' + map__id_num + '[_hash] = ...
}
/*
_keys = map_keys(_map_id, _key)
連想配列_map_idの_keyを列挙
cf. keys = keys(map{key})
*/
map_keys{
_id = _argv[0]
_keys = IARRAY
_size = EVAL('ARRAYSIZE(map__keys_' + map__id_num + ')')
for _i = 0; _i < _size; _i ++ {
_key = EVAL('map__keys_' + map__id_num + '[_i]')
if _key != IVOID {
_keys = (_keys, _key)
}
}
_keys
}
/*
_junk = map_destroy(_map_id)
連想配列_map_idを削除
*/
map_destroy{
_id = _argv[0]
ERASEVAR('map__keys_' + map__id_num)
ERASEVAR('map__values_' + map__id_num)
}
map__get_only_index{ // 重複しないようインデックスをずらす
_id = _argv[0]
_key = _argv[1]
_hash = map__hash(_key)
while (EVAL('map__keys_' + _id + '[_hash]') != IVOID) &...
if _hash >= (map__hash_size - 1){
_hash = 0
} else {
_hash++
}
}
_hash
}
map__hash{ // ハッシュ関数
_key = _argv[0]
_key_len = STRLEN(_key)
_hash = 0
for _i = 1; _i < _key_len; _i++ {
_hash = (_hash * 137 + CHRCODE(_key, _i)) % map__hash_...
}
_hash
}
* ハッシュ:引数渡しによる実装(おすすめ?) [#i2dc66e4]
巨大な引数渡しをする代わりに、自然なロジックと自然な変数...
** 利点 [#acf05691]
- 自然なロジックで実装できる
- ちゃんと連想配列がローカル変数である
** 欠点 [#o90d8cf7]
- 巨大な引数渡しが遅そう(実用上そう気になるレベルではない...
- 操作が返り値を使うなどやや奇妙
** 使用例 [#p9cef621]
// map__hash_size = 2048 // 一連想配列に確保するハッシュ...
_m = map_new() // 初期化して実体的な連想配列を取得
_m = map_set(_m, 'key', 'value') // 操作後の連想配列は返...
_k = map_get(_m, 'key')
_ks = map_keys(_m)
_m = map_delete(_m, 'key')
// 変数の開放は特に必要ない
** 実装 [#wb4a1f18]
/*
_map = map_new()
連想配列初期化
cf. map = {}
*/
map_new{
if ! ISVAR('map__hash_size') {
map__hash_size = 2048
}
IARRAY
}
/*
_map = map_set(_map, _key, _value)
連想配列_mapの_keyに_valueをセットした連想配列を返す
cf. map{key} = value
*/
map_set{
_key = _argv[_argc - 2]
_value = _argv[_argc - 1]
_argv[_argc - 2, _argc - 1] = IARRAY
_hash = map__get_only_index(_argv, _key)
_argv[_hash * 2] = _key
_argv[_hash * 2 + 1] = _value
_argv
}
/*
_value = map_get(_map, _key)
連想配列_mapの_keyを参照
cf. value = map{key}
*/
map_get{
_key = _argv[_argc - 1]
_argv[_argc - 1] = IARRAY
_hash = map__get_only_index(_argv, _key)
_argv[_hash * 2 + 1]
}
/*
_map = map_delete(_map, _key)
連想配列_mapの_keyを削除した連想配列を返す
cf. delete(map{key})
*/
map_delete{
_key = _argv[_argc - 1]
_argv[_argc - 1] = IARRAY
_hash = map__get_only_index(_argv, _key)
_argv[_hash * 2] = IVOID
_argv[_hash * 2 + 1] = _IVOID
_argv
}
/*
_keys = map_keys(_map, _key)
連想配列_mapの_keyを列挙
cf. keys = keys(map{key})
*/
map_keys{
_keys = IARRAY
for _i = 0; _i < _argc / 2; _i ++ {
_key = _argv[_i * 2]
if _key != IVOID {
_keys = (_keys, _key)
}
}
_keys
}
map__get_only_index{ // 重複しないようインデックスをずらす
_key = _argv[_argc - 1]
_argv[_argc - 1] = IARRAY
_hash = map__hash(_key)
while (_argv[_hash * 2] != IVOID) && (_argv[_hash * 2] ...
if _hash >= (map__hash_size - 1){
_hash = 0
} else {
_hash++
}
}
_hash
}
map__hash{ // ハッシュ関数
_key = _argv[0]
_key_len = STRLEN(_key)
_hash = 0
for _i = 1; _i < _key_len; _i++ {
_hash = (_hash * 137 + CHRCODE(_key, _i)) % map__hash_...
}
_hash
}
終了行:
YAYAで連想配列が使えないと聞いたので簡単なのを実装してみ...
どれが速いかわからないので数種類やってみた。
#contents
- バグがあったら報告してください。
- ライセンスは一応CC0とかで。
* ハッシュ:1つの連想配列メモリを使ってIDで区別する実装(微...
EVALと巨大な引数渡しを回避する方法
** 利点 [#qe980da8]
- EVAL等の遅そうな処理がない
** 欠点 [#g703bee3]
- 実行時全体のハッシュが一堂に会するので、要素数が多くな...
- EVAL等がない代わりにロジックは煩雑
- YAYAが変数を自動保存するので終了時に内部変数を削除しな...
- 操作関数の返り値を返さないのが面倒
** 使用例 [#m0cff258]
// map__hash_size = 65536 // 確保するハッシュ領域のサイ...
_m = map_new() // 初期化してIDを取得
_junk = map_set(_m, 'key', 'value')
_k = map_get(_m, 'key')
_ks = map_keys(_m)
_junk = map_delete(_m, 'key')
_junk = map_destroy(_m) // 削除して使えるハッシュ領域を...
_junk = map_destroy_all() // ハッシュ領域のグローバル変...
** 実装 [#ua34a828]
/*
_map_id = map_new()
連想配列初期化
cf. map = {}
*/
map_new{
if ! ISVAR('map__hash_size') {
map__hash_size = 65536
}
if ! ISVAR('map__id_num') {
map__id_num = 0
}
if ! ISVAR('map__key_lists') {
map__key_lists = IARRAY
}
if ! ISVAR('map__keys') {
map__keys = IARRAY
}
if ! ISVAR('map__values') {
map__values = IARRAY
}
map__id_num
map__id_num++
}
/*
_value = map_set(_map_id, _key, _value)
連想配列_map_idの_keyに_valueをセット
cf. map{key} = value
*/
map_set{
_id = _argv[0]
_key = _argv[1]
_value = _argv[2]
_hash = map__get_only_index(_id, _key)
// キーが事前に存在しないならmap__key_listsにキー情報を...
if map__keys[_hash] == IVOID {
map__key_lists = (map__key_lists, _id, _key)
}
map__keys[_hash] = _key
map__values[_hash] = _value
_value
}
/*
_value = map_get(_map_id, _key)
連想配列_map_idの_keyを参照
cf. value = map{key}
*/
map_get{
_id = _argv[0]
_key = _argv[1]
_hash = map__get_only_index(_id, _key)
map__values[_hash]
}
/*
_junk = map_delete(_map_id, _key)
連想配列_map_idの_keyを削除
cf. delete(map{key})
*/
map_delete{
_id = _argv[0]
_key = _argv[1]
_hash = map__get_only_index(_id, _key)
map__keys[_hash] = IVOID
map__values[_hash] = IVOID
}
/*
_keys = map_keys(_map_id, _key)
連想配列_map_idの_keyを列挙
cf. keys = keys(map{key})
*/
map_keys{
_id = _argv[0]
_size = ARRAYSIZE(map__key_lists) / 2
_keys = IARRAY
for _i = 0; _i < _size; _i++ {
if map__key_lists[_i * 2] == _id {
_key = map__key_lists[_i * 2 + 1]
_hash = map__get_only_index(_id, _key)
if map__values[_hash] != IVOID {
_keys = (_keys, _key)
}
}
}
_keys
}
/*
_junk = map_destroy(_map_id)
連想配列_map_idを削除
*/
map_destroy{
// keysによりmap__keys, map__values当該を消してからmap_...
_id = _argv[0]
_keys = map_keys(_id)
foreach _keys; _key {
_hash = map__get_only_index(_id, _key)
map__keys[_hash] = IVOID
map__values[_hash] = IVOID
}
_size = ARRAYSIZE(map__key_lists) / 2
_to_delete = IARRAY
for _i = 0; _i < _size; _i++ {
if map__key_lists[_i * 2] == _id {
_to_delete = (_to_delete, _i)
}
}
_to_delete = ASORT('int,descending', _to_delete)
foreach _to_delete; _i {
map__key_lists[_i * 2, _i * 2 + 1] = IARRAY
}
}
/*
_junk = map_destroy_all()
連想配列が使用する変数を削除
*/
map_destroy_all{
ERASEVAR('map__hash_size', 'map__id_num', 'map__key_lis...
}
map__get_only_index{ // 重複しないようインデックスをずらす
_id = _argv[0]
_key = _argv[1]
_hash_key = _id + TOSTR(_key)
_hash = map__hash(_hash_key)
while (map__keys[_hash] != IVOID) && (map__keys[_hash] ...
if _hash >= (map__hash_size - 1){
_hash = 0
} else {
_hash++
}
}
_hash
}
map__hash{ // ハッシュ関数
_key = _argv[0]
_key_len = STRLEN(_key)
_hash = 0
for _i = 1; _i < _key_len; _i++ {
_hash = (_hash * 137 + CHRCODE(_key, _i)) % map__hash_...
}
_hash
}
* ハッシュ:EVALによる実装(あり?) [#y4e0d20d]
EVALを使う代わりにより自然なロジックで実装できる。
** 利点 [#bfa2dc6f]
- 自然なロジックで実装できる
** 欠点 [#r10a7b82]
- EVALが遅そう(実用上そう気になるレベルではない気がする)
- 変数の削除はやはり必要。
- 操作関数の返り値を返さないのが面倒
** 使用例 [#weff16ed]
// map__hash_size = 2048 // 一連想配列に確保するハッシュ...
_m = map_new() // 初期化してIDを取得
_junk = map_set(_m, 'key', 'value')
_k = map_get(_m, 'key')
_ks = map_keys(_m)
_junk = map_delete(_m, 'key')
_junk = map_destroy(_m) // 変数開放
** 実装 [#s09bacb2]
/*
_map_id = map_new()
連想配列初期化
cf. map = {}
*/
map_new{
if ! ISVAR('map__hash_size') {
map__hash_size = 2048
}
if ! ISVAR('map__id_num') {
map__id_num = 0
}
LETTONAME('map__keys_' + map__id_num, IARRAY)
LETTONAME('map__values_' + map__id_num, IARRAY)
map__id_num
map__id_num++
}
/*
_value = map_set(_map_id, _key, _value)
連想配列_map_idの_keyに_valueをセット
cf. map{key} = value
*/
map_set{
_id = _argv[0]
_key = _argv[1]
_value = _argv[2]
_hash = map__get_only_index(_id, _key)
_junk = EVAL('map__keys_' + map__id_num + '[_hash] = _k...
_junk = EVAL('map__values_' + map__id_num + '[_hash] = ...
_value
}
/*
_value = map_get(_map_id, _key)
連想配列_map_idの_keyを参照
cf. value = map{key}
*/
map_get{
_id = _argv[0]
_key = _argv[1]
_hash = map__get_only_index(_id, _key)
EVAL('map__values_' + map__id_num + '[_hash]')
}
/*
_junk = map_delete(_map_id, _key)
連想配列_map_idの_keyを削除
cf. delete(map{key})
*/
map_delete{
_id = _argv[0]
_key = _argv[1]
_hash = map__get_only_index(_id, _key)
_junk = EVAL('map__keys_' + map__id_num + '[_hash] = IV...
_junk = EVAL('map__values_' + map__id_num + '[_hash] = ...
}
/*
_keys = map_keys(_map_id, _key)
連想配列_map_idの_keyを列挙
cf. keys = keys(map{key})
*/
map_keys{
_id = _argv[0]
_keys = IARRAY
_size = EVAL('ARRAYSIZE(map__keys_' + map__id_num + ')')
for _i = 0; _i < _size; _i ++ {
_key = EVAL('map__keys_' + map__id_num + '[_i]')
if _key != IVOID {
_keys = (_keys, _key)
}
}
_keys
}
/*
_junk = map_destroy(_map_id)
連想配列_map_idを削除
*/
map_destroy{
_id = _argv[0]
ERASEVAR('map__keys_' + map__id_num)
ERASEVAR('map__values_' + map__id_num)
}
map__get_only_index{ // 重複しないようインデックスをずらす
_id = _argv[0]
_key = _argv[1]
_hash = map__hash(_key)
while (EVAL('map__keys_' + _id + '[_hash]') != IVOID) &...
if _hash >= (map__hash_size - 1){
_hash = 0
} else {
_hash++
}
}
_hash
}
map__hash{ // ハッシュ関数
_key = _argv[0]
_key_len = STRLEN(_key)
_hash = 0
for _i = 1; _i < _key_len; _i++ {
_hash = (_hash * 137 + CHRCODE(_key, _i)) % map__hash_...
}
_hash
}
* ハッシュ:引数渡しによる実装(おすすめ?) [#i2dc66e4]
巨大な引数渡しをする代わりに、自然なロジックと自然な変数...
** 利点 [#acf05691]
- 自然なロジックで実装できる
- ちゃんと連想配列がローカル変数である
** 欠点 [#o90d8cf7]
- 巨大な引数渡しが遅そう(実用上そう気になるレベルではない...
- 操作が返り値を使うなどやや奇妙
** 使用例 [#p9cef621]
// map__hash_size = 2048 // 一連想配列に確保するハッシュ...
_m = map_new() // 初期化して実体的な連想配列を取得
_m = map_set(_m, 'key', 'value') // 操作後の連想配列は返...
_k = map_get(_m, 'key')
_ks = map_keys(_m)
_m = map_delete(_m, 'key')
// 変数の開放は特に必要ない
** 実装 [#wb4a1f18]
/*
_map = map_new()
連想配列初期化
cf. map = {}
*/
map_new{
if ! ISVAR('map__hash_size') {
map__hash_size = 2048
}
IARRAY
}
/*
_map = map_set(_map, _key, _value)
連想配列_mapの_keyに_valueをセットした連想配列を返す
cf. map{key} = value
*/
map_set{
_key = _argv[_argc - 2]
_value = _argv[_argc - 1]
_argv[_argc - 2, _argc - 1] = IARRAY
_hash = map__get_only_index(_argv, _key)
_argv[_hash * 2] = _key
_argv[_hash * 2 + 1] = _value
_argv
}
/*
_value = map_get(_map, _key)
連想配列_mapの_keyを参照
cf. value = map{key}
*/
map_get{
_key = _argv[_argc - 1]
_argv[_argc - 1] = IARRAY
_hash = map__get_only_index(_argv, _key)
_argv[_hash * 2 + 1]
}
/*
_map = map_delete(_map, _key)
連想配列_mapの_keyを削除した連想配列を返す
cf. delete(map{key})
*/
map_delete{
_key = _argv[_argc - 1]
_argv[_argc - 1] = IARRAY
_hash = map__get_only_index(_argv, _key)
_argv[_hash * 2] = IVOID
_argv[_hash * 2 + 1] = _IVOID
_argv
}
/*
_keys = map_keys(_map, _key)
連想配列_mapの_keyを列挙
cf. keys = keys(map{key})
*/
map_keys{
_keys = IARRAY
for _i = 0; _i < _argc / 2; _i ++ {
_key = _argv[_i * 2]
if _key != IVOID {
_keys = (_keys, _key)
}
}
_keys
}
map__get_only_index{ // 重複しないようインデックスをずらす
_key = _argv[_argc - 1]
_argv[_argc - 1] = IARRAY
_hash = map__hash(_key)
while (_argv[_hash * 2] != IVOID) && (_argv[_hash * 2] ...
if _hash >= (map__hash_size - 1){
_hash = 0
} else {
_hash++
}
}
_hash
}
map__hash{ // ハッシュ関数
_key = _argv[0]
_key_len = STRLEN(_key)
_hash = 0
for _i = 1; _i < _key_len; _i++ {
_hash = (_hash * 137 + CHRCODE(_key, _i)) % map__hash_...
}
_hash
}
ページ名: