web-dev-qa-db-ja.com

テーブルにLuaの要素が含まれているかどうかを確認する方法

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

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

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

89
Wookai

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

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

より完全な機能の例があります here

113
interjay

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

24
Norman Ramsey

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

2
Joel

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

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

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つのポインターを格納するため、追加のメモリオーバーヘッドは比較的小さくなります。テーブルが非常に小さい場合、それははるかに重要ではなく、実際には、別のマップ検索を行うよりも反復する方が速い場合があります。

ただし、質問の文言は、処理するアイテムが多数あることを強く示唆しています。

2
James