web-dev-qa-db-fra.com

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

Existe-t-il une méthode pour vérifier si une table contient une valeur? J'ai ma propre fonction (naïve), mais je me demandais s'il existait quelque chose d '"officiel" 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 raison principale pour laquelle j'utilise cette fonction est d'utiliser des tableaux en tant qu'ensembles, c'est-à-dire sans éléments dupliqués. Y a-t-il autre chose que je pourrais utiliser?

89
Wookai

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 .

113
interjay

Compte tenu de votre représentation, votre fonction est aussi efficace que possible. Bien sûr, comme l'ont noté d'autres personnes (et pratiquées dans des langues plus anciennes que Lua), la solution à votre problème réel est de changer de représentation. Lorsque vous avez des tables et que vous voulez des jeux, vous transformez les tables en jeux en utilisant l'élément set en tant que clé et true en tant que valeur. +1 à l'interjay.

24
Norman Ramsey

Je ne vois pas d'autre moyen de comparer les valeurs, mais si vous utilisez l'élément de l'ensemble comme clé, vous pouvez définir la valeur sur autre chose que nil. Vous obtenez alors des recherches rapides sans avoir à chercher dans toute la table.

2
Joel

Je sais que ceci est un ancien post, mais je voulais ajouter quelque chose pour la postérité. La manière simple de traiter le problème que vous avez est de créer une autre table, d’une valeur à l’autre.

c'est à dire. vous avez 2 tables qui ont la même valeur, l'une pointant dans une direction, l'une pointant dans 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 interroger la nouvelle table pour voir si elle a la clé 'element'. Cela évite d'avoir à parcourir chaque valeur de l'autre table.

S'il s'avère que vous ne pouvez pas réellement utiliser l'élément comme clé, parce que ce n'est pas une chaîne par exemple, ajoutez une somme de contrôle ou tostring par exemple, puis utilisez-la comme clé. .

Pourquoi veux-tu faire cela? Si vos tables sont très grandes, le temps nécessaire pour parcourir chaque élément sera considérable, 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 vos tables sont très petites, cela importera beaucoup moins. En fait, il peut même être plus rapide à itérer que d'avoir une autre recherche sur la carte.

Le libellé de la question suggère toutefois fortement que vous ayez un grand nombre de points à traiter.

2
James