2016-02-19 41 views
1

我有這樣一個匿名的Lua功能:的Lua不走了「零」表

an_func = function(x) return x == nil end 

我需要從4個值測試它的表:{'None', nil, 1, '1'}。 所以,我寫了下面的代碼:

for num, element in pairs({'None', nil, 1, '1'}) do 
    print(num .. ': ' .. tostring(an_func(element))) 
end 

當我跑了,我只拿到了三條線:

1: false 
3: false 
4: false 

true值(對應於nil表元素)的行不打印。

你能解釋一下,爲什麼Lua會打印所有結果,但是true?我怎樣才能修復它的輸出全部4行?

P.S.我是Lua的新手。

+0

你已經標記了這個[數組],幾個答案和註釋使用術語「數組」。這是令人困惑的,因爲它可能指的是Lua實現的內部數據結構,或者2)暗示不會從其他編程環境中繼承的特性。這就是爲什麼文檔定義了[序列表]的概念(http://www.lua.org/manual/5.3/manual.html#2.1)。您的表格構造函數不會生成包含序列的表格。 –

回答

5

使用pairs()時,它遍歷表的所有元素。 意味着沒有,所以它不會超過它。爲什麼它應該告訴你桌子上什麼都沒有?如果你有一張全新的桌子,如果你用任何東西做索引,它將返回print(({}).test) --> nil

如果你真的想要得到的零,你可以使用一個虛擬值:

local NIL = setmetatable({},{__tostring=function() return "nil" end}) 

an_func = function(x) return x == NIL end 

for num, element in pairs({'None', NIL, 1, '1'}) do 
    print(num .. ': ' .. tostring(an_func(element))) 
end 

輸出:

1: false 
2: true 
3: false 
4: false 
+0

據我所知,你已經添加了一個metatable(類似於Python或Java中的屬性)到**所有表格**,帶有'NIL'。即使我沒有在metatable中爲'__tostring'分配一個匿名函數,它也適用於我。什麼是創建'__tostring'的原因? – VeLKerr

+2

@VeLKert事實上他做了一張名爲NIL的表,當tostring'd返回'nil'時 – warspyking

+0

在他的特殊例子中,他根本不需要metatable,他只是這樣做,所以如果你打印它,你會得到預期值'nil' – warspyking

3

在Lua中,一切(函數,字符串,線程,...)是一個值,其中nil(和技術上無/ void)是唯一的例外。簡而言之,nil代表值爲缺席。所以當迭代一張桌子時,爲什麼Lua會說那裏什麼都沒有。如果這樣做,它將不得不迭代你可以創建的每個可能的索引。

但是看起來你正在使用一個數組。你技術上可以迭代它假設你知道長度。我將假設表格中的最後一項是不是nil,並且在帶有孔的表的最初長度之後沒有指定任何孔,但是在您的情況下,這可能不一定是真的,if它是不是你將不得不繼續跟蹤長度自己的,並使用它,而不是#操作符:

for i = 1,#t do 
    local v = t[i] 
    print (v == nil) 
end 
+1

由於如何定義長度運算符,您確實假設數組部分中沒有空洞。 '表t的長度只有在表是一個序列時才被定義''{10,20,nil,40}不是一個序列,因爲它有4個密鑰,但沒有3個密鑰。' http: //www.lua.org/manual/5.3/manual.html#3.4.7 – Rochet2

+0

@ Rocket2然而在你的例子中,#運營商會給我4個。我明白你在說什麼,但#操作員是如何工作的,我可以用這種方式來使用它。 – warspyking

+0

你可以做任何你想做的事。但是沒有什麼能保證你在所有情況下所做的行爲都將如預期那樣。 (未定義的行爲)下面是一個例子,顯示當以相同的表格以不同的方式定義時,長度操作符具有不同的行爲:https://repl.it/Bo97 – Rochet2

1

你會通過你要打印的值的所有密鑰需要循環。 可能的方法:

  1. 事先知道長度。 (warspyking注意到這一點)
  2. 使用結束標記。
  3. 以某種方式計算長度(例如用maxn)。
  4. 使用某些東西來表示零值。 (EinsteinK顯示的示例的這一 )

每個人都有好的和壞的方面,這裏有一些:

對於第一個你需要事先知道這可能是困難的所有情況下的長度。 結束標記很方便,但要求您移動結束標記。 如果最後一個元素爲零,則計算長度將不起作用。

計算長度的示例 - 假定最後一個元素不是零。 請注意,lua 5.1有table.maxn,您可以使用它來代替這個自定義的maxn實現。使用的結束標記的

an_func = function(x) return x == nil end 

function maxn(t) 
    local n = 0 
    for k,v in pairs(t) do 
     if k%1 == 0 then 
      n = k 
     end 
    end 
    return n 
end 

local t = {'None', nil, 1, '1'} 
for num = 1, maxn(t) do 
    print(num .. ': ' .. tostring(an_func(t[num]))) 
end 

實施例:

an_func = function(x) return x == nil end 

local END = {} 
local t = {'None', nil, 1, '1', END} 

local num = 1 
while t[num] ~= END do 
    print(num .. ': ' .. tostring(an_func(t[num]))) 
    num = num+1 
end 
+0

maxn已被棄用,我不認爲你應該建議它。出於好奇,既然你只是在處理數組,爲什麼不使用ipairs呢?我覺得我失去了一些東西。 – warspyking

+0

ipairs在第一個零停止,所以我沒有看到我將如何以任何方式使用它來代替任何一個循環 - 它將在打印第一個值後停止。 maxn本身就是它應該做的工作的工具。我想我推薦table.maxn,因爲如果它在C或其他東西中實現可能會更快。雖然它被刪除是啊..嗯。 所有這些解決方案都適用於數組中的任何洞 - 除了maxn假定最後一個元素永遠不會爲零,否則任何值都可以爲零。 – Rochet2

+0

噢,對不起,暫時的腦部疾病。但我仍然不會推薦ipairs,即使是5.1版本,它也會引入不兼容性,並且無論如何都被棄用。 – warspyking