在Lua中,如何执行a-b函数,其中a和b是数组或表?

我是一名新程序员,使用 Lua 开始学习。我想实现数组 a-b 的功能,以下是我的程序,但其运行效果不佳。

function delTwo (a ,b)
local i = 0
   local lengthA = #a
   local lengthB = #b

  for i = 1 ,lengthA do
   for j =1 , lengthB do
   if a[i]==b[j] then
   a[i] = nil
   end
  end

  for i = 1 , lengthA do
   if a[i]~= nil then
   retrun a[i]
   end
  end
  end

  end

a = {10, 20, 30}
b={11,20,122}
for element in delTwo (a ,b)  do
  print(element)
end

我有两个问题,第一个是输入:16: '=' expected near 'a' retrun a[i] Y 应该改为 retrun =a[i],两者有何区别?

第二个是输入:3: attempt to get length of local 'a' (a nil value) 无论我将其改为 local lengthA = table.getn(a),仍然会出现输入:3: bad argument #1 to 'getn' (table expected, got nil) 的错误提示。这是什么问题?

原文链接 https://stackoverflow.com/questions/4039802

点赞
stackoverflow用户206020
stackoverflow用户206020

第一个问题已经有答案了,但是第二个问题是指在程序的某个执行点,a 变成了 nil(等同于 null)。不过我试着用你的例子重复了一下也没能够出现这种情况。

我不是很确定你想要做什么,但是我建议你先创建一个新表来存储所需的结果,然后使用 pairs(或者普通循环)来迭代。像下面这样:

function delTwo(a, b)
    local result = {}
    --# 在这里加入逻辑。
    --# 使用 result[#result + 1] = ... 来插入值。
    return result
end

for k, v in pairs(delTwo(a,b)) do print(k, v) end
2010-10-28 05:41:15
stackoverflow用户319344
stackoverflow用户319344

使用元表的另一种版本

local mt = {    --// 创建元表的基础
__sub = function (a, b) --// 函数与 Zecc 相同,只是格式略有不同
    local lengthB = #b
    for j = 1, lengthB do
        local lengthA = #a
        for i = 1, lengthA do
            if a[i] == b[j] then table.remove(a, i) end
        end
    end
    return a
end
}

a = {10, 20, 30}    --// 相同的数组
b = {11, 20, 122}

setmetatable(a, mt) -- //使用它来给数组提供 __sub 函数
setmetatable(b, mt)

c = a - b   --// 然后你可以在其上使用数学运算符

for k, v in ipairs(c) do --// 打印它们将得到与上面相同的结果
    print(k, v)
end

然后,如果您想以同样的方式使用不同的数组,只需使用 setmetatable(x, mt),其中 x 是您想要拥有该函数的表,它应该能够工作。

2010-11-09 23:01:31
stackoverflow用户2303714
stackoverflow用户2303714

下面是我实现的函数,它可以执行以下操作的功能:

  1. 从A中减去x元素,从B中减去y元素(如果B中存在y元素)
function arrDel(a,b)
        local result = {}
        for i = 1, #a, 1 do
            result[i] = a[i] - ( b[i] or 0) -- 'or 0'存在是为了解决b的长度小于a的情况
        end
        return result
end

此代码创建并填充名为result的表,该表是从a中减去b的“结果”。在lua中存在两种类型的for循环:数字循环和通用循环。上述函数中的循环利用了数字类型的循环。当需要执行其中包含的代码块已知次数次数,或者索引以查找循环使用的值时,应使用此循环。

语法如下:

for counter = initial, final, increment do
  body
end

增量是可选的,默认为1。


为了演示另一种类型的循环,此小函数打印出一个非常简单的表:

function tprint(t)
    local res = {}
    for _,v in ipairs(t) do
       res[#res+1] = v
    end
    print("{"..table.concat(res,",").."}")
end

这里使用通用循环(使用'in'关键字)。通用循环允许轻松遍历复杂对象。例如,假设一个对象包含用户记录,但记录存储在部分中,即VIP,管理员,来宾等...但是您想浏览所有用户。您可以编写一个函数,然后在通用for循环中使用该函数,轻松使用类似于以下表达式的表达式:

for user in object.traverseUsers() do
  body
end

此类迭代器的实现超出了本问题的范围,但可以在此处找到一个很好的解释Generic For (PIL)

2013-04-21 07:39:47
stackoverflow用户7700268
stackoverflow用户7700268
  1. 你把 "return" 拼写成了 "retrun"。

  2. 如果存在可能会提供除表格以外的其他东西,但你仍想让代码保持运行状态,可以使用以下代码

    local lengthA = a and #a or 0
    local lengthB = b and #b or 0
    
  3. 并不是很必要,不过只是一些小信息;无需这样说

       if a[i] ~= nil then
    

    可以使用以下代码代替:

     if a then
    
2017-03-15 18:56:28
stackoverflow用户8261525
stackoverflow用户8261525

问题类似于集合差异,下面的函数准备了一个字典,其中包含从数组b中可能要删除的值,并在遍历时检查数组a是否包含它。该函数具有可选的inplace标志,如果在原地进行更改,将替换数组a,否则返回一个新的数组。

function arrayDiff(a,b,inplace)
  inplace = inplace~=false -- 默认inplace
  local ret = inplace and a or {}
  local toRemove = {} -- 一个字典,包含要删除的值
  for i=1,#b do toRemove[b[i]]=true end
  local nxtInsert = 0
  local aLen = #a
  for i=1,aLen do
    local value = a[i]
    if not toRemove[value] then
      nxtInsert = nxtInsert + 1
      ret[nxtInsert] = value
    end
  end
  if inplace then
    for i=nxtInsert+1,aLen do ret[i]=nil end
  end
  return ret
end
2017-08-01 15:35:44