2017-04-14 104 views
3

我想實現一個函數,該函數從傳遞給它的變量中返回第一個非空字符串。不幸的是,一些變量可能是零,所以很自然的做法如何創建一個返回傳遞給它的第一個非零,非空字符串的函數?

function first_non_empty(...) 
    for i, item in ipairs({...}) do 
     if item ~= nil and item ~= '' then 
      return item 
     end 
    end 
    return '' 
end 

不起作用:ipairs儘快退出了,因爲它遇到一個零值。這可以通過改變需求來修改,以便變量不能爲零,或者通過將長度傳遞給函數,因此表長度不必依賴於ipairs,或者通過將所有參數封裝在函數中,他們明確沒有

function first_non_empty_func(...) 
    for i, func in ipairs({...}) do 
     local item = func() 
     if item ~= nil and item ~= '' then 
      return item 
     end 
    end 
    return '' 
end 

function fn(p) 
    local f = function() return p end 
    return f 
end 

-- change callers to first_non_empty_func(fn(a), fn(b), fn(c)) 

但是,這些解決方案都使函數原型複雜化。是否存在一個採用有序參數列表的函數,其中一些參數可能爲零,它將返回非零的非零參數和不爲空字符串的第一個參數?

回答

3

select('#', ...)可以用來獲取提供的參數個數,所以這裏不使用table.pack一種替代方案:

function first_non_empty_pack(...) 
    for i = 1, select('#', ...) do 
     local item = select(i, ...) 
     if item ~= nil and item ~= '' then 
      return item 
     end 
    end 
    return '' 
end 
+0

不錯!作爲獎勵,因爲'select'在5.1中出現,而'table.pack'不在,我可以在Scribunto中使用它。 –

+0

@ChrisMidgley'函數table.pack(...)return {n = select('#',...),...} end'就是全部。對於long vararg列表,重複複製'select'調用的列表可能比創建一次表並慢慢迭代要慢。另一方面,創建需要稍後垃圾回收的表可能會變慢。所以基準測試可以看出哪一個在你的案例中更快(或者只是選擇你認爲更清潔的一個,直到你看到速度實際上是一個問題)。 – nobody

4

使用table.pack,它保留了所有零條目,並返回在n領域的條目數:

function first_non_empty_pack(...) 
    local t = table.pack(...) 
    for i = 1, t.n do 
     local item = t[i] 
     if item ~= nil and item ~= '' then 
      return item 
     end 
    end 
    return '' 
end 
1

簡單的方法是使用遞歸。沒有創建額外的表格等:

function first_non_empty(item, ...) 
    if item ~= nil and item ~= '' then return item end 
    return first_non_empty(...) 
end 

但是列表必須以一些結束標記結束。例如,boolean'false',表示沒有非零非空字符串。

+0

不需要結束標誌,'選擇(「#」,.. 。)== 0'可以用作停止條件。避免重複的「select」調用的另一種方法是首先確定計數,然後如'item local = rec(n,item,...)那樣倒計數,如果item〜= nil和item〜=''則返回item elseif n> 0,然後返回rec(n-1,...)end end function first_non_empty(...)return rec(select('#',...),...)end end'。 – nobody

+0

結束標記使得這個函數更快,更簡單。另外,結束標記可以不是布爾值,而是一些後備字符串值,當沒有找到其他字符串時應該返回。這可以節省一些此功能之外的檢查。這一切都取決於實際需要,而這個功能只是其中的一種:) – Vlad

相關問題