Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/lua/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Performance 确定两个表是否具有相同的键集_Performance_Lua_Set - Fatal编程技术网

Performance 确定两个表是否具有相同的键集

Performance 确定两个表是否具有相同的键集,performance,lua,set,Performance,Lua,Set,我使用Lua表作为集合,方法是将集合的值放在表键中,并将1作为表值,例如 function addToSet(s,...) for _,e in ipairs{...} do s[e]=1 end end function removeFromSet(s,...) for _,e in ipairs{...} do s[e]=nil end end local logics = {} addToSet(logics,true,false,"maybe") 为了测试两个集合是否相

我使用Lua表作为集合,方法是将集合的值放在表键中,并将
1
作为表值,例如

function addToSet(s,...)      for _,e in ipairs{...} do s[e]=1   end end
function removeFromSet(s,...) for _,e in ipairs{...} do s[e]=nil end end

local logics = {}
addToSet(logics,true,false,"maybe")

为了测试两个集合是否相等,我需要确保它们具有完全相同的键。执行此操作的有效方法是什么?

在两个表中循环,并确保键在另一个表中有值。一旦发现不匹配项,立即失败,如果两项都通过,则返回
true
。对于大小
M
N
的集合,这是O(M+N)复杂度

function sameKeys(t1,t2)
  for k,_ in pairs(t1) do if t2[k]==nil then return false end end
  for k,_ in pairs(t2) do if t1[k]==nil then return false end end
  return true
end
在行动中看到:

local a,b,c,d = {},{},{},{}
addToSet(a,1,2,3)
addToSet(b,3,1,2,3,3,1)
addToSet(c,1,2)
addToSet(d,2,1)
print(sameKeys(a,b)) --> true
print(sameKeys(a,c)) --> false
print(sameKeys(d,c)) --> true

注意:测试
t[k]==nil
要比只测试
而不是t[k]
好得多,因为您为表条目设置了
false
值,并且希望密钥出现在集合中。

既然您询问了效率,我将提供一个替代实现。根据预期的输入表,您可能希望避免第二个循环的查找。如果期望表相同,则效率更高;如果存在差异,则效率更低

function sameKeys(t1,t2)
  local count=0
  for k,_ in pairs(t1) do
    if t2[k]==nil then return false end
    count = count + 1
  end
  for _ in pairs(t2) do
    count = count - 1
  end
  return count == 0
end
另一个版本避免查找,除非它们是必要的。这可能在另一组用例中执行得更快

function sameKeys(t1,t2)
  local count=0
  for _ in pairs(t1) do count = count + 1 end
  for _ in pairs(t2) do count = count - 1 end
  if count ~= 0 then return false end
  for k,_ in pairs(t1) do if t2[k]==nil then return false end end
  return true
end

编辑:经过更多的研究和测试,我得出结论,您需要区分Lua和LuaJIT。对于Lua,性能特征由Lua的解析器控制,因此由源代码标记的数量决定。对于Lua来说,这意味着Phrogz的版本很可能是更快的选择。对于LuaJIT来说,情况发生了巨大的变化,因为解析器不再是一个问题。对于几乎所有的情况,我展示的第一个版本都是一个改进,第二个版本可能在表非常大的情况下是最好的。我建议每个人都运行自己的基准测试,并检查哪个版本在他们的环境中工作得最好。

此外,如果查找是最昂贵的部分,您可以首先进行“仅计数”检查,并且只有在键数匹配时,才自己比较键。在任何情况下,您都希望根据您的实际数据对不同的备选方案进行基准测试。在Lua中,查找任何值的成本都不高也不低。在使用一组特定的集合进行测试时,上述解决方案的速度分别比可接受的答案慢约1.5倍和2倍。好主意,但最终既不简单也不性能。我用LuaJIT测试了它(我们说的是性能,对吧?),用一些测试集,我的第二个版本比你的版本快10倍。正如我所说的:这取决于您拥有的用例。
false
是表中的有效值,如果不是t2[k]将丢失它。@finnw是的。请参阅我的答案中从“注意”开始的部分。它不仅不适用于问题,而且也由答案来处理。是的,但它是一个脚注,第一个版本比第二个版本没有优势,所以为什么不只使用第二个版本呢?@finnw一个公平的观点;性能是一样的,保存两个字符是不值得的。编辑。