Comment vérifier si une table contient un élément dans Lua?

Est-il une méthode pour vérifier si une table contient une valeur ? J'ai ma propre fonction (naïve), mais je me demandais si quelque chose de "Officiel" existait pour cela ? Ou quelque chose de plus efficace...

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

En passant, la principale raison pour laquelle j'utilise ces fonctions est d'utiliser des tables comme ensembles, c'est-à-dire sans éléments en double. Est-il autre chose que je pourrais utiliser ?

81
demandé sur hjpotter92 2010-02-17 19:32:32

4 réponses

Vous pouvez mettre les valeurs comme clés de la table. Par exemple:

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

Il y a un exemple plus complet ici .

104
répondu interjay 2013-02-11 02:07:41

Compte tenu de votre représentation, Votre fonction est aussi efficace que possible.{[3] } Bien sûr, comme noté par d'autres (et comme pratiqué dans des langues plus anciennes que Lua), la solution à votre vrai problème est de changer de représentation. Lorsque vous avez des tables et que vous voulez des ensembles, vous transformez les tables en ensembles en utilisant l'élément set comme clé et true comme valeur. +1 à interjay.

23
répondu Norman Ramsey 2014-04-24 20:03:25

Je ne peux pas penser à une autre façon de comparer les valeurs, mais si vous utilisez l'élément de l'ensemble comme clé, vous pouvez définir la valeur à autre chose que nil. Ensuite, vous obtenez des recherches rapides sans avoir à rechercher la table entière.

2
répondu Joel 2010-02-17 16:43:37

Je sais que c'est un vieux post, mais je voulais ajouter quelque chose pour la postérité. La façon simple de gérer le problème que vous avez est de créer une autre table, de valeur à clé.

Ie. vous avez 2 tables qui ont la même valeur, une pointant une direction, une pointant l'autre.

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

Vous pouvez ensuite d'interroger la nouvelle table pour voir si elle a la clé "élément". Cela évite d'avoir à parcourir chaque valeur de l'autre table.

S'il S'avère que vous ne pouvez pas réellement utilisez 'element' comme clé, car ce n'est pas une chaîne par exemple, puis ajoutez une somme de contrôle ou 'toString' dessus par exemple, puis utilisez-la comme clé.

Pourquoi voulez-vous faire cela? Si vos tables sont très volumineuses, le temps nécessaire pour parcourir chaque élément sera important, ce qui vous empêchera de le faire très souvent. La surcharge de mémoire supplémentaire sera relativement faible, car elle stockera 2 pointeurs sur le même objet, plutôt que 2 copies du même objet. Si votre les tables sont très petites, alors cela importera beaucoup moins, en fait, il peut même être plus rapide d'itérer que d'avoir une autre recherche de carte.

Le libellé de la question suggère cependant fortement que vous avez un grand nombre d'éléments à traiter.

2
répondu James 2013-09-02 09:15:40