【问题标题】:Comparing two index tables by index-value in lua在lua中通过索引值比较两个索引表
【发布时间】:2012-02-02 02:29:30
【问题描述】:

我正在尝试将两个长度相等的表与一个函数进行比较,因为我不知道有任何其他方法可以做到这一点。但是,使用以下功能,它无法注册,我不知道为什么。我希望有人可以提供对此问题的见解,或者有更好的方法来比较这两个表。

使用以下代码填充表格:

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)和计数为 1(第三个位置的三个)。我认为最难的部分之一是通过比较来识别猜测中的第二个 4 根本不应该增加 Pcount。

【问题讨论】:

    标签: lua compare lua-table


    【解决方案1】:

    您的代码应该可以工作的轻微变体是:

    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 听起来您在比较状态而不是通用表。在这种情况下,您可能想使用一些 OO lua 魔法来做到这一点。我将在第二个答案中概述。
    • 尝试了上述两种解决方案,尽管表相同,但都返回 false。
    • @Josh 你和它比较的表是什么?我在上面添加了一个为我打印正确值的示例。
    • 我用 for i=1,4 do table.insert(puzzle,math.random(4)) 创建了一个谜题,并使用上面的第一个代码,我使用拼图桌。两者在正确的索引处都有相同的数字,但它返回 false。
    【解决方案2】:

    如果您在面向对象的意义上比较对象比表格更客观的对象,那么我会考虑以 lua OO 方式实现这些功能。

    这样的事情应该可以解决问题:

    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 )
    

    【讨论】:

    • “自我”从何而来?刚试了一下,它返回一个错误,说它正在尝试索引本地自我,一个 nil 值。编辑:哦,等等,我在第一个街区看到它。奇怪的是,它返回一个错误。
    • @Josh 你在哪里看到这个错误? (我已经在我的 lua 副本上测试了这个,它运行没有错误)。
    • (\n 只是表示新行,因为 cmets 不允许多行)使用 wxLuaeditor 和上面的两个代码部分,它返回:状态 1 是:\n 错误:Lua:错误运行块时 \n [string "*untitled.lua"]:18: 尝试索引本地 'self' (一个 nil 值) \n 堆栈回溯: \n [string "*untitled.lua"]:18: 在函数中'print' \n [string "*untitled.lua"]:37: in main chunk
    • 将 state1.print() 更改为 print(state1) 似乎已修复它。现在我可以使用它,看看如何在程序中使用它!谢谢!
    • @Josh .. 抱歉复制粘贴错误...试图显示使用 print 函数的 state1:print() 添加到元表和使用 __tostringprint(state1)元表工作。 (注意: 而不是.)我已经编辑了源代码来修复它。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-02-23
    • 2019-01-03
    • 2022-09-30
    • 2012-09-23
    • 1970-01-01
    • 2014-01-13
    • 2012-07-16
    相关资源
    最近更新 更多