Jak sprawdzić, czy tabela zawiera element w Lua?

Czy istnieje metoda sprawdzania, czy tabela zawiera wartość ? Mam swoją (naiwną) funkcję, ale zastanawiałem się, czy istnieje coś "oficjalnego" do tego? Albo coś bardziej wydajnego...

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

Przy okazji, głównym powodem, dla którego używam tej funkcji, jest używanie tabel jako zestawów, tj. bez duplikatów elementów. Czy jest coś jeszcze, czego mógłbym użyć ?

Author: hjpotter92, 2010-02-17

4 answers

Wartości można umieścić jako klucze tabeli. Na przykład:

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

Jest bardziej w pełni funkcjonalny przykład tutaj .

 104
Author: interjay,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-02-11 02:07:41

Biorąc pod uwagę twoją reprezentację, twoja funkcja jest tak wydajna, jak to tylko możliwe. Oczywiście, jak zauważyli inni (i jak praktykowali w językach starszych niż Lua), rozwiązaniem Twojego prawdziwego problemu jest zmiana reprezentacji. Gdy masz tabele i chcesz mieć zestawy, zamieniasz tabele w zestawy, używając elementu set jako klucza i true jako wartości. +1 do interjay.

 23
Author: Norman Ramsey,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-04-24 20:03:25

Nie mogę wymyślić innego sposobu porównywania wartości, ale jeśli użyjesz elementu zestawu jako klucza, możesz ustawić wartość na cokolwiek innego niż nil. Następnie otrzymujesz szybkie wyszukiwanie bez konieczności przeszukiwania całego stołu.

 2
Author: Joel,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-02-17 16:43:37

Wiem, że to stary post, ale chciałem dodać coś dla potomności. Prostym sposobem obsługi problemu, który masz, jest utworzenie innej tabeli, o wartości do klucza.

Ie. masz 2 tabele, które mają tę samą wartość, jeden wskazuje w jednym kierunku, jeden wskazuje w drugim.

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

Możesz następnie odpytywać nową tabelę, aby sprawdzić, czy ma klucz "element". Zapobiega to konieczności iteracji przez każdą wartość drugiej tabeli.

Jeśli okaże się, że nie możesz użyj 'element' jako klucza, ponieważ nie jest to na przykład ciąg znaków, a następnie dodaj na nim na przykład sumę kontrolną lub 'toString', a następnie użyj tego jako klucza.

Dlaczego chcesz to zrobić? Jeśli Twoje tabele są bardzo duże, czas na powtórzenie każdego elementu będzie znaczący, co uniemożliwi ci robienie tego bardzo często. Dodatkowy narzut pamięci będzie stosunkowo mały, ponieważ będzie przechowywał 2 wskaźniki do tego samego obiektu, a nie 2 kopie tego samego obiektu. Jeśli tabele są bardzo małe, wtedy będzie to miało znacznie mniejsze znaczenie, w rzeczywistości może być nawet szybciej iterację niż mieć inne wyszukiwanie map.

Sformułowanie pytania sugeruje jednak, że masz wiele spraw do załatwienia.

 2
Author: James,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-09-02 09:15:40