Luaでテーブルに要素が含まれているかどうかを確認するにはどうすればよいですか?


97

テーブルに値が含まれているかどうかを確認する方法はありますか?私は自分の(素朴な)機能を持っていますが、そのために「公式」なものが存在するのではないかと思っていました。またはもっと効率的なもの...

function table.contains(table, element)
  for _, value in pairs(table) do
    if value == element then
      return true
    end
  end
  return false
end

ちなみに、この関数を使用している主な理由は、テーブルをセットとして使用することです。つまり、重複する要素がないためです。他に使用できるものはありますか?


3
_、表記はどういう意味ですか?
マーティン

24
これは、単に「ガベージ」という名前の変数です_pairs()はを返しますkey, valueが、この例では値のみが必要です。この変数を使用して不要なものを格納することは、慣例の1つ(「Luaのプログラミング」lua.org/pil/index.htmlで採用_です。
Wookai

_PythonとJavaScriptで使用される「ガベージ」変数の命名規則も見ました。
iono

回答:


116

値をテーブルのキーとして置くことができます。例えば:

function addToSet(set, key)
    set[key] = true
end

function removeFromSet(set, key)
    set[key] = nil
end

function setContains(set, key)
    return set[key] ~= nil
end

ここには、より完全な機能を備えた例があります


13
匿名ユーザーがコードに次の修正を提案しました:指定されたキーを持つセットの値がFALSEの場合、指定されたキーを持つテーブルに項目があるにもかかわらず、関数setContains()はfalseを返します。「return set [key]〜= nil」という行はそのエラーを修正します。
12

おそらくまたfunction keysOfSet(set) local ret={} for k,_ in pairs(set) do ret[#ret+1]=k end return ret end
ジェシーチザム2018

24

あなたの表現が与えられれば、あなたの関数はできる限り効率的です。 もちろん、他の人が指摘しているように(そしてLuaより古い言語で実践されているように)、実際の問題の解決策は表現を変更することです。テーブルがあり、セットが必要な場合は、set要素をキーおよびtrue値として使用して、テーブルをセットに変換します。インタージェイに+1。


2

値を比較する別の方法は考えられませんが、セットの要素をキーとして使用すると、値をnil以外に設定できます。次に、テーブル全体を検索する必要なく、高速なルックアップが得られます。


2

これは古い記事であることは知っていますが、後世のために何かを追加したかったのです。あなたが持っている問題を処理する簡単な方法は、キーに値の別のテーブルを作成することです。

すなわち。同じ値を持つ2つのテーブルがあり、1つは1つの方向を指し、1つは他の方向を指します。

function addValue(key, value)
    if (value == nil) then
        removeKey(key)
        return
    end
    _primaryTable[key] = value
    _secodaryTable[value] = key
end

function removeKey(key)
    local value = _primaryTable[key]
    if (value == nil) then
        return
    end
    _primaryTable[key] = nil
    _secondaryTable[value] = nil
end

function getValue(key)
    return _primaryTable[key]
end

function containsValue(value)
    return _secondaryTable[value] ~= nil
end

次に、新しいテーブルにクエリを実行して、キー「要素」があるかどうかを確認します。これにより、他のテーブルのすべての値を反復処理する必要がなくなります。

「要素」を文字列ではないなどの理由で実際にキーとして使用できないことが判明した場合は、たとえばチェックサムまたはそのtostring上に追加して、それをキーとして使用します。

なぜこれをしたいのですか?テーブルが非常に大きい場合、すべての要素を反復処理するための時間が非常に長くなり、頻繁に実行することができなくなります。同じオブジェクトの2つのコピーではなく、同じオブジェクトへの2つのポインタを格納するため、追加のメモリオーバーヘッドは比較的小さくなります。テーブルが非常に小さい場合、問題ははるかに少なく、事実、別のマップルックアップよりも反復処理の方が高速です。

ただし、質問の文言は、対処すべき項目が多数あることを強く示唆しています。


良い説明ですが、ディスカッションには何も追加されません。おそらくインタージェイの答えを編集した方がいいでしょう。
bcdan 2015年

1
また、「。key」はこのコードのすべての場所で「[key]」に置き換える必要があります(「value」と同じ)
Njol
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.