2

一部の値 (オプションや関数の引数など) が一部のモデルと一致するかどうかを確認するためのスクリプトがあります。スクリプトで再帰的なデータ構造をチェックできるようにしたいです。問題は、すでにチェックされているリストと辞書への参照を含むリストを反復処理するよりも効率的な方法があるかどうかです。コード例:

function s:AlreadyChecked(arg, checkedlst)
    if type(a:arg)!=type([]) && type(a:arg)!=type({})
        return 0
    endif
    for obj in a:checkedlst
        if a:arg is obj
            return 1
        endif
    endfor
    call add(a:checkedlst, a:arg)
    return 0
endfunction

checkedlstソートする方法(つまり、参照を比較するが、それらによって見つかった値を比較しない) や、ハッシュを使用する方法を探しています。

4

1 に答える 1

1

既にお気付きだと思いますが、Vim では List または Dictionary 変数を辞書のキーとして使用することはできません。つまり、たとえば、次のように「チェック済み」の辞書を作成することはできません。

" Unless k is a String, this won't work.
:let checked[k] = 1

また、リストまたは辞書から一意の文字列を生成する簡単な方法がないため、これも信頼できません。

:let checked[ string(k) ] = 1

より良いアプローチは、ハッシュテーブルを構築しようとする代わりに、データ構造自体をマークすることです。データ構造を一時的に読み取り専用にすることを気にしない場合、その方法の 1 つは次を使用すること:lockvarです。

:let someDict = {}
:let someDict['foo'] = [1, 2, 3]
:lockvar 1 someDict

someDictそれは読み取り専用としてマークされます。(1はロックをディクショナリのトップ レベルに制限するため、ネストされた構造は自動的にロックされません。) 変数のロック状態は、次のように調べることができます。

:echo islocked('someDict')
1

:echo islocked("someDict['foo']")
0

:echo islocked("someDict['foo'][0]")
0

ロック解除も簡単です:

:unlockvar 1 someDict

これで、ネストされたデータ構造の個々のレベルを「チェック済み」としてマークする手法、特定のレベルがマークされているかどうかを照会する方法、および完了時にすべてのマークを削除する方法が得られました。すべてをまとめると、AlreadyChecked()次のように変更できます。

function! s:AlreadyChecked(arg, checkedlst)

    if type(a:arg)!=type([]) && type(a:arg)!=type({})
        return 0
    endif

    " If this particular List or Dictionary has already been checked, just
    " return true immediately.
    "
    if islocked('a:arg')
        echo "Already checked."
        return 1
    endif

    " Lock the List or Dictionary to mark this item as already
    " checked. Note that only the top level of the List or Dictionary
    " is locked; values are not locked.
    "
    lockvar 1 a:arg

    " Remember everything we've locked, so it can be unlocked once
    " we're done.
    "
    call add(a:checkedlst, a:arg)

    return 0

endfunction

チェックが完了したら、すべてのロックを削除します。

for obj in a:checkedlst
    unlockvar 1 obj
endfor

お役に立てれば。これはロック機能のハックな悪用ですが、おそらく必要なことは実行してくれるでしょう。

于 2010-07-18T06:01:28.797 に答える