Bir Lua tablosunun boş olup olmadığını (giriş içermediğini) belirlemenin en etkili yolu?


120

Bir tablonun boş olup olmadığını belirlemenin en etkili yolu nedir (yani, şu anda ne dizi stili değerleri ne de dikte stili değerleri içerir)?

Şu anda kullanıyorum next():

if not next(myTable) then
    -- Table is empty
end

Daha verimli bir yol var mı?

Not: #bu sadece tabloda dizi tarzı değerlerine faaliyet olarak operatör, burada yeterli değildir - bu nedenle #{test=2}ayırt edilemez #{}tablo değişkeni ise de dönüp 0. Ayrıca bu denetimi dikkat çünkü nilben aramıyorum olarak yeterli durumdadır gelmez nil değerleri, bunun yerine 0 girişli tablolar (yani {}).

Yanıtlar:


151

Kodunuz verimli ama yanlış. (Düşünün {[false]=0}.) Doğru kod

if next(myTable) == nil then
   -- myTable is empty
end

Maksimum verimlilik nextiçin yerel bir değişkene bağlanmak isteyeceksiniz , örn.

...
local next = next 
...
... if next(...) ...

1
Teknik doğruluk konusunda iyi bir nokta; Orijinal kodu kullandığım belirli durumlarda, falsebeklenen bir anahtar olmazdı , bu yüzden if notiyi çalıştı, ancak muhtemelen nilgelecekte bunun yerine iyi bir alışkanlık olarak karşılaştırmayı alışkanlık haline getireceğim . Ve evet, hız için ortak yardımcı program işlevlerini yerel değişkenlere bağladım. Yine de girdi için teşekkürler.
Amber

1
Kod amaçlandığı gibi çalıştığında yanlışlığı kabul etmekte zorlanıyorum
RD Alkire

4
Neden yaparak hız kazanıyoruz local next?
Moberg

2
@Moberg Bu, LUA'nın ad alanını işleme biçiminden kaynaklanmaktadır. Çok basitleştirilmiş versiyon, önce yerel tablolara tırmanacak, yani local nextmevcut blokta bir varsa, onu kullanacak, sonra bir sonraki bloğa tırmanacak ve tekrar edecek. Yerellerden çıktıktan sonra, ancak o zaman Global Ad Alanı'nı kullanacaktır. Bu, basitleştirilmiş bir sürümüdür, ancak sonuçta, program hızıyla ilgili olarak kesinlikle fark anlamına gelir.
ATaco

@Moberg, lua 5.2 ve 5.3 bağlamında daha az basitleştirilmiş sürüm, yerel olmayanların ya upvals ya da _ENV aramaları olmasıdır. Bir yukarı değer, fazladan bir yönlendirme katmanından geçmek zorundadır, oysa _ENV araması bir tablo aramadır. Oysa bir yerel,
VM'de bir kayıttır

1

Bir olasılık, metatable "newindex" anahtarını kullanarak elemanların sayısını saymak olabilir. Olmayan bir şeyi atarken nil, sayacı artırın (sayaç, metatable'da da yaşayabilir) ve atarken nilsayacı azaltın.

Boş tablo için test, sayacı 0 ile test etmek olacaktır.

Metatable belgelere bir işaretçi burada

Yine de çözümünüzü beğendim ve dürüst olmak gerekirse, çözümümün genel olarak daha hızlı olduğunu varsayamıyorum.


5
Asıl soru sadece "dizi" girişlerini saymakla ilgili değil.
lhf

3
0x6'nın önerisi dizi tarzı girişlere özgü değildir (yeni dizin hem sayısal hem de sayısal olmayan dizinler için çalışır). Ancak, nilanahtar tabloda zaten mevcutsa __newindex tetiklenmediğinden , asıl sorun ne zaman atandığını tespit etmektir.
Amber

3
Bu hilenin işe yaraması için, metatable'ın her ikisini de uygulaması __indexve __newindexgerçek verileri bir gölge tabloda depolaması ve gerçek tabloyu boş tutması gerekir, böylece __indexçağrılabilir. Yüksek sesle düşündüğümde, her bir aramanın artan maliyetinin buna değmeyeceğinden şüpheleniyorum.
RBerteig

0

Muhtemelen istediğin buydu:

function table.empty (self)
    for _, _ in pairs(self) do
        return false
    end
    return true
end

a = { }
print(table.empty(a))
a["hi"] = 2
print(table.empty(a))
a["hi"] = nil
print(table.empty(a))

Çıktı:

true
false
true

11
next()döngüden daha etkilidir (ve daha özlüdür) pairs().
Amber

8
Aslında, döngü pairs() yapmak aslında sadece next()tekniği kullanmaktır , ancak daha fazla ek yük ile.
şüphelijim

7
Ayrıca, standart tablekitaplığa yazmak tavsiye edilmez.
Ti Strga

-1

Aşırı yüklenmişse __eq değerinin değerlendirilmesinden kaçınmak daha iyidir.

if rawequal(next(myTable), nil) then
   -- myTable is empty
end

veya

if type(next(myTable)) == "nil" then
   -- myTable is empty
end

1
Ben bu cevabın neden reddedildiğini anlamaya çalışan bir Lua çaylakıyım. Sanırım bunun nedeni Lua'da "iki nesnenin farklı meta yöntemleri varsa, eşitlik işlemi herhangi bir meta yöntemi çağırmadan yanlış sonuçlanır". (Bu alıntı Lua'da Programlama lua.org'dan bu sayfanın altındadır ). Bu, sıfır için __eq aşırı yüklemesinden kaçınma ihtiyacını ortadan kaldırıyor mu?
SansWit

-1

yılanı dene, benim için çalış

serpent = require 'serpent'

function vtext(value)
  return serpent.block(value, {comment=false})
end

myTable = {}

if type(myTable) == 'table' and vtext(myTable) == '{}' then
   -- myTable is empty
end

-2

Buna ne dersin ?

if endmyTable[1] == nil then
  -- myTable is empty
end

1
Bu, dizinler gibi dizeler olan bir masada çalışmaz
SamHoque

-3

Bunun eski olduğunu biliyorum ve sizi bir şekilde yanlış anlıyor olabilirim, ancak masanın boş olmasını istersiniz, yani sadece olup olmadığını kontrol etmediğiniz ve gerçekten boş olmasını istemediğiniz veya buna ihtiyaç duymadığınız sürece, Yanılmıyorsam, basitçe yeniden oluşturarak temizleyebilirsiniz. bu aşağıdaki sözdizimi ile yapılabilir.

yourtablename = {} -- this seems to work for me when I need to clear a table.

4
Soru bu değil.
Yu Hao

-6

Kullanmayı deneyin #. Bir tablodaki tüm örnekleri döndürür. Tabloda örnek yoksa, döner0

if #myTable==0 then
print('There is no instance in this table')
end

1
Soruyu soran kişi bunun #yeterli olmayacağını söylüyor ve nedenini açıklıyor; Bunun neden bu nedenlerden kaynaklandığını açıklayabilir misiniz?
2017

iyi ... bilmiyorum.
bunda yeniyim
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.