Bir tablonun Lua'da bir öğe içerip içermediğini nasıl kontrol edebilirim?


99

Bir tablonun bir değer içerip içermediğini kontrol etmenin bir yöntemi var mı? Kendi (saf) işlevim var, ama bunun için "resmi" bir şey var mı diye merak ediyordum? Veya daha verimli bir şey ...

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

Bu arada, bu işlevleri kullanmamın ana nedeni, tabloları kümeler olarak, yani yinelenen öğeler olmadan kullanmaktır. Kullanabileceğim başka bir şey var mı?


3
_, gösterimi ne anlama geliyor?
Martin

24
Bu, adında bir "çöp" değişkendir _. pairs()döner key, value, ancak bu örnekte sadece değere ihtiyacım var. İhtiyaç duyulmayan_ şeyleri depolamak için bu değişkeni kullanmak bir tür kuraldır ( " Lua'da Programlama" lua.org/pil/index.html kitabında benimsenmiştir ) .
Wookai

_Python ve JavaScript'te kullanılan "garbage" değişkenlerini adlandırma kuralını da gördüm .
iono

Yanıtlar:


118

Değerleri tablonun anahtarları olarak koyabilirsiniz. Örneğin:

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

Burada daha tam özellikli bir örnek var .


13
Anonim bir kullanıcı, kodunuza aşağıdaki düzeltmeyi önerdi: Belirtilen anahtara sahip kümedeki değer FALSE ise, bu durumda setContains () işlevi, tabloda belirtilen anahtara sahip bir öğe olmasına rağmen bir yanlış döndürür. "return set [key] ~ = nil" satırı bu hatayı düzeltir.
oers

Belki defunction keysOfSet(set) local ret={} for k,_ in pairs(set) do ret[#ret+1]=k end return ret end
Jesse Chisholm

24

Sunumunuz göz önüne alındığında, işleviniz olabildiğince verimli. Elbette, başkalarının da belirttiği gibi (ve Lua'dan daha eski dillerde uygulandığı gibi), gerçek probleminizin çözümü temsilinizi değiştirmektir. Tablolarınız olduğunda ve setler istediğinizde, set öğesini anahtar ve truedeğer olarak kullanarak tabloları setlere dönüştürürsünüz . Interjay'e +1.


3

Bunun eski bir gönderi olduğunu biliyorum ama gelecek nesil için bir şeyler eklemek istedim. Sahip olduğunuz sorunu ele almanın basit yolu, anahtar değeri olan başka bir tablo yapmaktır.

yani. aynı değere sahip, biri bir yönü gösteren, biri diğerini gösteren 2 tablonuz var.

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

Daha sonra yeni tabloyu, anahtar "element" e sahip olup olmadığını görmek için sorgulayabilirsiniz. Bu, diğer tablonun her değerini yineleme ihtiyacını önler.

Örneğin bir dize olmadığı için 'element'i aslında bir anahtar olarak kullanamayacağınız ortaya çıkarsa, o zaman örneğin tostringüzerine bir sağlama toplamı ekleyin ve sonra bunu anahtar olarak kullanın.

Bunu neden yapmak istiyorsun? Tablolarınız çok büyükse, her öğe üzerinde yineleme yapmak için gereken süre önemli olacaktır ve bu da çok sık yapmanıza engel olacaktır. Ek bellek yükü, aynı nesnenin 2 kopyası yerine aynı nesneye 2 işaretçi depolayacağından nispeten küçük olacaktır. Tablolarınız çok küçükse, çok daha az önemli olacaktır, hatta yinelemek başka bir harita aramasına göre daha hızlı olabilir.

Bununla birlikte, sorunun ifadesi, ilgilenmeniz gereken çok sayıda öğenizin olduğunu güçlü bir şekilde göstermektedir.


İyi bir açıklama, ancak tartışmaya pek bir şey katmıyor. Interjay'in cevabını düzenlemek muhtemelen daha iyi bir fikir olurdu.
bcdan

1
Ayrıca, '.key' bu kodun her yerinde '[key]' ile değiştirilmelidir ('value' ile aynı)
Njol

2

Değerleri karşılaştırmanın başka bir yolunu düşünemiyorum, ancak anahtar olarak kümenin öğesini kullanırsanız, değeri sıfır dışında herhangi bir değere ayarlayabilirsiniz. Ardından, tüm tabloyu aramak zorunda kalmadan hızlı aramalar elde edersiniz.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.