在Lua中通过索引值比较两个索引表

5
我正在尝试使用一个函数比较两个长度相等的表格,因为我不知道其他方法。然而,使用以下函数时,它无法注册,我不知道原因。希望有人能提供这个问题的见解或更好的比较这两个表格的方法。
这些表格是由以下代码填充的:
str = "parameters determined by program (all digits)"
tableone = {}
for word in str:gmatch("%d") do table.insert(tableone,word) end

这两个表格是完全相同的,除了表格名称不同之外。这些表格已经被正确地填充,并且在打印时显示正常。以下是两个表格的示例:

tableone = {}
tabletwo = {}
for i=1,4 do table.insert(tableone, i) end
for i=1,4 do table.insert(tabletwo, i) end

显然,这两个表将彼此相等。我编写的比较索引表的函数如下:
function comparetables(t1, t2)
matchct = 0
 for i=1,#t1 do
    if t1[i] == t2[i] then
    matchct = matchct + 1
    end
if matchct == #t1 then
return true
end
end

我尝试了一下。
print(comparetables(tableone,tabletwo))

我希望能看到它打印出"true",但没有成功。对我来说,它似乎应该毫无问题地工作。但它没有。我已经尝试搜索类似于table.compare函数的东西,但没有找到。感谢任何建议!

额外的信息:

我比较表格的原因是为了一个大师球员类型的游戏。这意味着在比较表时必须遵循以下三个规则。我创建的函数只是让我开始思考,以便从那里开始工作。

  1. 当比较表时,如果数字匹配,则Ccount增加1。
  2. 当比较表时,如果值存在于不同的索引位置中,则将Pcount增加1。

例如,使用值{1, 3, 3, 4}和猜测{4, 4, 3, 1}的表将返回Pcount为2(一个4和1)和Ccount为1(第三个位置的三)。我认为最困难的部分之一将是使比较认识到猜测中的第二个4根本不会增加Pcount。

2个回答

5
您的代码稍微有些变化,可以尝试以下方式:

以下是可行的代码变体:

function comparetables(t1, t2)
  if #t1 ~= #t2 then return false end
  for i=1,#t1 do
    if t1[i] ~= t2[i] then return false end
  end
  return true
end

但我更多地使用类似于这样的内容:它检查参数的类型、元表和其他几种情况。

-- This is not clever enough to find matching table keys
-- i.e. this will return false
--   recursive_compare( { [{}]:1 }, { [{}]:1 } )
-- but this is unusual enough for me not to care ;)
-- It can also get stuck in infinite loops if you use it on 
-- an evil table like this:
--     t = {}
--     t[1] = t

function recursive_compare(t1,t2)
  -- Use usual comparison first.
  if t1==t2 then return true end
  -- We only support non-default behavior for tables
  if (type(t1)~="table") then return false end
  -- They better have the same metatables
  local mt1 = getmetatable(t1)
  local mt2 = getmetatable(t2)
  if( not recursive_compare(mt1,mt2) ) then return false end

  -- Check each key-value pair
  -- We have to do this both ways in case we miss some.
  -- TODO: Could probably be smarter and not check those we've 
  -- already checked though!
  for k1,v1 in pairs(t1) do
    local v2 = t2[k1]
    if( not recursive_compare(v1,v2) ) then return false end
  end
  for k2,v2 in pairs(t2) do
    local v1 = t1[k2]
    if( not recursive_compare(v1,v2) ) then return false end
  end

  return true  
end

这是一个使用它的例子:
print( recursive_compare( {1,2,3,{1,2,1}}, {1,2,3,{1,2,1}} ) ) -- prints true
print( recursive_compare( {1,2,3,{1,2,1}}, {2,2,3,{1,2,3}} ) ) -- prints false

我假设第一段代码中有一个错误的“for”语句。我可能应该提到我比较表格的原因。我正在创建一个类似猜数字游戏的游戏,所以它需要检查值来a.)看看它们是否全部匹配,b.)看看是否有任何匹配项,如果有,记录数量,c.)看看这些数字是否存在于表格中,并跟踪计数。将在问题中更新此信息。 - Josh
@Josh 听起来像是你在比较状态而不是通用表格。在这种情况下,你可能想使用一些面向对象的 Lua 魔法来实现它。我将在第二个答案中概述。 - Michael Anderson
尝试了上述两种解决方案,但是两者都返回了 false,尽管表格是相同的。 - Josh
@Josh 你用来比较的表是哪些?我已经添加了一个示例,对我来说打印出了正确的值。 - Michael Anderson
我用 for i=1,4 do table.insert(puzzle,math.random(4)) 创建了一个谜题,并使用上面的第一段代码,根据谜题表中的信息生成了猜测表。两者在正确的索引处都有相同的数字,但它返回了 false。 - Josh
让我们在聊天中继续这个讨论 - Michael Anderson

3
如果你比较的对象在面向对象的意义上更像是对象而不是表,那么我建议你采用lua面向对象的方式实现这个功能。以下代码应该可以解决问题:
GameState = {}
GameState.mt = {}
GameState.mt.fns = {}
GameState.mt.__index =  GameState.mt.fns

function GameState.new(a,b,c,d)
-- TODO: put argument checks here...
  local retval = {}
  retval[1] = a
  retval[2] = b
  retval[3] = c
  retval[4] = d
  setmetatable(retval, GameState.mt)
  return retval
end

function GameState.mt.fns.print( self )
  print(" GameState: ", self[1], self[2], self[3], self[4] )
end

function GameState.mt.__tostring( self )
  return "GameState: "..self[1].." "..self[2].." "..self[3].." "..self[4]
end

function GameState.mt.__eq(self, other)
  -- Check it's actually a GameState, and all its bits match
  return getmetatable(other)==GameState.mt and
    (self[1] == other[1]) and 
    (self[2] == other[2]) and 
    (self[3] == other[3]) and 
    (self[4] == other[4])
end

那么你可以像这样使用它:

state1 = GameState.new(1,2,3,4)
state2 = GameState.new(1,2,3,4)

print("State 1 is:")
state1:print()

print("State 2 is:")
print(state2)

print( "state1 == state2 : ", state1 == state2 )

print( "Changing state 2") 
state2[1]=2

print( "state1 == state2 : ", state1 == state2 )

“self” 是从哪里来的?我刚试了一下,它返回错误说正在尝试索引 local self,一个空值。编辑:哦,等等,我在第一个块中看到了它。不过这返回错误还是有点奇怪。 - Josh
@Josh,你在哪里看到这个错误?(我已经在我的Lua副本上测试过它了,没有错误)。 - Michael Anderson
使用wxLuaeditor和上面的两个代码部分,它返回以下内容:\n 状态1为:\n 错误:Lua:运行块时出错\n [string "*untitled.lua"]:18:尝试索引本地变量'self'(一个空值)\n 堆栈回溯:\n [string "*untitled.lua"]:18:在函数'print'中\n [string "*untitled.lua"]:37:在主块中 - Josh
将state1.print()更改为print(state1)似乎已经修复了它。现在我可以使用它并且看看如何在程序中使用它!谢谢! - Josh
@Josh..抱歉复制粘贴错误...我试图展示state1:print()print(state1)两者都能工作的原因是,前者使用了添加到元表中的print函数,而后者使用了元表中的__tostring。(请注意使用:而不是.)我已经编辑了源代码来修复这个问题。 - Michael Anderson

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接