6

キーが他のluaテーブルであるluaテーブルを保存したい。これが可能であることはわかっていますが、それらのテーブルのコピーを使用してテーブル内でルックアップを実行できるようにしたいと考えています。具体的には、次のことができるようになりたいです。

t = {}
key = { a = "a" }
t[key] = 4
key2 = { a = "a" }

そして、私は検索できるようにしたい:

t[key2]

そして4を得る。

key文字列に変換して table に入れることができることを知っていますt。また、カスタム ハッシュ関数を作成するか、テーブルをネストしてこれを行うことも考えました。このタイプの機能を取得するための最良の方法はありますか? 他にどのようなオプションがありますか?

4

6 に答える 6

8

Lua では、別々に作成された 2 つのテーブルは「異なる」と見なされます。しかし、一度テーブルを作成すると、それを任意の変数に割り当てることができ、それらを比較すると、Lua はそれらが等しいことを教えてくれます。言い換えると:

t = {}
key = { a = "a" }
t[key] = 4
key2 = key
...
t[key2] -- returns 4

だから、それはあなたが望むことをするためのシンプルでクリーンな方法です. どこかに保管して、それを使用してバックをkey取り出すことができます. 4これも非常に高速です。

どうしてもやりたくない場合は、方法があります。しかし、それは一種の非効率的で醜いです。

最初の部分は、2 つの別々のテーブルを比較する関数を作成することです。2 つのテーブルが「同等」である場合は true を返し、そうでない場合は false を返します。それを同等と呼びましょう。次のように動作するはずです。

equivalent({a=1},{a=1})          -- true
equivalent({a=1,b=2}, {a=1})     -- false
equivalent({a={b=1}}, {a={b=2}}) -- false

テーブル自体を含むテーブルを処理するために、関数は再帰的でなければなりません。テーブルの 1 つが他のテーブルを「含んでいる」が、より多くの要素を持っている場合にもだまされてはなりません。私はこの実装を思いつきました。おそらくもっと良いものがあります。

local function equivalent(a,b)
  if type(a) ~= 'table' then return a == b end

  local counta, countb = 0, 0

  for k,va in pairs(a) do
    if not equivalent(va, b[k]) then return false end
    counta = counta + 1
  end

  for _,_ in pairs(b) do countb = countb + 1 end

  return counta == countb
end

ここではその機能について説明しません。それが何をするのかが十分に明確であることを願っています。

パズルの他の部分は、キーを比較するときに関数をt使用することです。equivalentこれは、メタテーブルを慎重に操作し、追加の「ストレージ」テーブルを使用して行うことができます。

私たちは基本的tに偽者に変身します。コードがキーの下に値を保存するように指示した場合、それ自体は保存されません。代わりに、それを追加のテーブルに渡します (これを と呼びますstore)。コードが値を要求tすると、 で値を検索しますstoreが、関数を使用してequivalent値を取得します。

これはコードです:

local function equivalent(a,b)
... -- same code as before
end

local store = {} -- this is the table that stores the values

t = setmetatable({}, {
  __newindex = store,
  __index = function(tbl, key)
    for k,v in pairs(store) do
      if equivalent(k,key) then return v end
    end
  end
})

使用例:

t[{a = 1}] = 4

print(t[{a = 1}]) -- 4
print(t[{a = 1, b = 2}]) -- nil
于 2012-02-08T22:41:25.403 に答える
2

これは Lua では不可能です。テーブルをキーとして使用する場合、キーはテーブルの特定の「インスタンス」です。同じ内容で別のテーブルを作ってもインスタンスが違うので別キーです。

このようなことをしたい場合は、一種のハッシュ関数を作成して、テーブルをトラバースしてキーとして機能させ (必要に応じて再帰的に行うこともできます)、テーブル コンテンツの文字列表現を作成できます。異なるコンテンツでは異なり、同じコンテンツのテーブルでは同じである限り、人間が読める形式である必要はありません。を使用してテーブルをトラバースするのとは別にpairs()、キーをテーブルに挿入し、 を使用してソートする必要があります。これは、キーをtable.sort()任意pairs()の順序で返し、「等しい」テーブルに同じ文字列が必要なためです。

このような文字列を作成したら、それをキーとして使用できます。

function hash(t) ... end
t = {}
key1 = { a = "a", b = "b" }
t[hash(key1)] = 4
key2 = { a = "a", b = "b" }
print(t[hash(key2)]) -- should print "4" if the hash function works correctly

私の意見では、これはインデックス作成という単純なタスクには複雑すぎるため、テーブルのコピーを使用してインデックス作成することを考え直した方がよいかもしれません。なぜそのような機能が必要なのですか?

アップデート

フレーズだけを操作する必要がある場合は、それらを連結する方が、このような一般的なハッシュ関数を作成するよりも簡単だと思います。フレーズのシーケンスに必要な場合は、実際にテーブルを反復処理してキーをソートする必要はなく、各フレーズから主な情報を収集するだけです。適切なキーを作成できるヘルパー関数を使用する必要があります。

function pkey(...)
    local n, args = select('#', ...), { ... }
    for i=1,n do args[i] = args[i].value end -- extract your info here
    return table.concat(args, ' ') -- space or other separator, such as ':'          
end
tab[pkey(phrase1, phrase2, phrase3)] = "value"
于 2012-02-08T22:28:48.030 に答える
1

言語処理と、プログラムで到達したい目標についてはよくわかりませんが、次のようなトークンの収集についてはどうですか: ネストされたテーブル構造を使用して、インデックス テーブルに最初のフレーズ トークンによってインデックス付けされたテーブルのみを格納するようにします。次に、各サブテーブルには、2 番目のフレーズ トークンによってインデックス付けされた値が含まれます ... など ... フレーズの最終トークンに到達するまで、フレーズの出現に対応する数値にインデックスが付けられます。

次の 2 つのフレーズがある場合は、例を使用するとより明確になる可能性があります。

  • 私はバナナが好きです。
  • ホットチックが好きです。

インデックスの構造は次のとおりです。

index["I"] = {
    ["like"] = {
        ["banana"] = 1,
        ["hot"] = {
            ["chick"] = 1
        }
    }    
}

そうすれば、単一のトラバーサル ステップで頻度をカウントし、インデックス作成と同時に発生をカウントできますが、前に述べたように、それはあなたの目標が何であるかに依存し、フレーズを再分割することを意味します。インデックスから出現を見つけます。

于 2012-02-16T20:45:53.307 に答える
0

あなたがこれを行うことができるかどうかはわかりません。メタテーブルを使用してテーブルの等価性を定義できますが、ハッシュ関数を定義する方法はありません。等価性を定義するだけでは、必要なことを実行できるとは思えません。明らかに同等性を定義してpairs()から、キーを使用して自分でテーブルを反復処理することもできますが、これにより、O(1)ルックアップする必要のあるものがに変わりますO(n)

于 2012-02-08T21:27:05.760 に答える