• lua 4 使用table实现其他数据结构,并介绍遍历方法


    本文会以vector / map / set 这三种数据类型的角度来梳理 table 支持的不同遍历方式。

    table as std::vector

    一般,C/C++中的 array / vector (下文简称 vector) 是没有 key。但是在 lua 中使用了 table 这种通用结构,就引入了 key 的问题。

    在这里,把想用做 vector 的 table,做一个非常重要的约定:1 初始,key 连续。由于 table 的自由度很高,这个需要开发者自己约束。

    ---- 新建

    t = {"A", "BB", "CCC"} -- 默认的key就是1初始且连续
    
    -- 或者
    t = {} -- 建立一个空的
    t[1] = 1
    t[2] = 2
    t[3] = 3
    
    -- 或者
    t = {  
        [1] = 1,  
        [2] = 2,  
        [3] = 3,  -- 这里逗号可有可无
    }
    

      

    ---- 模拟 pushback

    vector = {}
    function vector.pushback(vec, val)
      vec[#vec + 1] = val
    end
    
    v = {}
    vector.pushback(v, 1)
    vector.pushback(v, 2)
    vector.pushback(v, 3)
    

      

    ---- 遍历,使用 ipairs,按照key从1开始,从小到大返回元素。

    for key, value in ipairs(v) do
      print(key, value)
    end
    

     

    table as std::map 用key寻值,无重复。 通用情况

    ---- 新建

    m = {["A"] = 1, ["BB"] = 2, ["CCC"] = 3} 
    m = {["A"] = 1, ["BB"] = "string2", 10 = 3}  -- key 和 value 的数据类型不必相同,自由伴随着控制的难度,一定程度上,key 和 value 推荐使用相同的类型。value 也可以是 table。handle 这种情况需要注意更多。
    
    -- 或者
    m = {} -- 建立一个空的
    m[1] = 1
    m[2] = 2
    m["3"] = 3 -- 打印结果和 3 一样,可以通过 type 判断类型差别。详见后续例子
    
    -- 或者
    m = {  
        [1] = 1,  
        [2] = 2,  
        ["3"] = 3,  -- 这里逗号可有可无
    }
    

      

    ---- 模拟 insert,不会重复插入

    map = {}
    function map.insert(map, key, val)
      map[key] = val
    end
    
    m = {["A"] = "str1"}
    map.insert(m, 1, 25)
    map.insert(m, "1", 5)
    map.insert(m, 1, 2)
    map.insert(m, 1, 25)
    

    ---- 查询元素,有就是1,没有就是0

    function map.have(map, key)
      if map[key] == nil then
        return false
      else
        return true
      end
    end
    
    m = {["A"] = "str1"}
    map.insert(m, 1, 25)
    map.insert(m, "1", 5)
    map.insert(m, 1, 2)
    map.insert(m, 1, 25)
    
    print(map.have(m, "A"))
    print(map.have(m, A))
    
    ------- 结果 --------
    true
    false
    

      

    ----遍历,使用 pairs(),按照 key 的 harsh 值大小排序输出。注意,顺序这个概念在 map 中并不重要

    for key, value in pairs(m) do
      print(key, type(key), value, type(value))
    end
    

      

    table as std::map 特殊情况:key 为数字,但不连续,希望从小到大遍历,或相反。

    使用迭代器(自定义的)

    -- from: program in Lua
    function pairsByKeys(t)
        local a = {}
        for n in pairs(t) do 
          a[#a + 1] = n 
        end
        table.sort(a) -- 默认升序
      -- table.sort(a, function(a1, a2) return a1 > a2 end) -- 降序
        local i = 0
        return function ()
            i = i + 1
            return a[i], t[a[i]]
        end
    end
    

      

    完整示例:

    map = {}
    function map.insert(map, key, val)
      map[key] = val
    end
    
    function map.have(map, key)
      if map[key] == nil then
        return false
      else
        return true
      end
    end
    
    -- from: program in Lua
    function pairsByKeys(t)
        local a = {}
        for n in pairs(t) do 
          a[#a + 1] = n 
        end
        table.sort(a)
        local i = 0
        return function ()
            i = i + 1
            return a[i], t[a[i]]
        end
    end
    
    m = {}
    map.insert(m, 1, 10)
    map.insert(m, 3, 30)
    map.insert(m, 9, 90)
    map.insert(m, 5, 50)
    
    print("pairsByKeys")
    for key, value in pairsByKeys(m) do
      print(key, value)
    end
    
    print("pairs")
    for key, value in pairs(m) do
      print(key, value)
    end
    
    ----------- 结果 ------------
    pairsByKeys
    1	10
    3	30
    5	50
    9	90
    pairs
    1	10
    9	90
    5	50
    3	30
    

      

    table as std::set 有序、不重复

    这里的 map 和 set 的差别就是在插入的时候,需要对所有数据按照 key 排序,从小到大。在lua 里,map 已经没有重复的 key。

    ---- 新建

    s = {}
    s = {1,2,3}
    s = {"A", "B", "C"} --> 字符串排序的规则需要自己定义
    

    ---- 模拟 insert,需要指定 value 的比较方式。set 是升序排列的,key 值不可改(注意赋值方式),所以需要指定 value 的比较方式。

    set = {}
    function set.insert(_s, val, _f) -- _f 就是需要自定义的比较函数,作为外部参数输入。详见后续
      _s[#_s + 1] = val
      if #_s > 1 then
        table.sort(_s, _f)
      end
    end

    ---- 判断元素有无

    set = {}
    function set.have(s, key)
      if s[key] == nil then
        return false
      else
        return true
      end
    end
    

    ---- 迭代所有元素使用:ipairs()

    for key, value in ipairs(s) do
      print(key, value)
    end

    ---- 完整示例  

    set = {}
    function set.insert(_s, val, _f)
      _s[#_s + 1] = val
      if #_s > 1 then
        table.sort(_s, _f)
      end
    end
    
    function set.have(s, key)
      if s[key] == nil then
        return false
      else
        return true
      end
    end
    
    -- you need to define a function to sort values in ascending order.
    function f(currenyVal, nextVal)
      return currenyVal < nextVal -- number
    end
    
    s = {}
    set.insert(s, 1, f)
    set.insert(s, 3, f)
    set.insert(s, 9, f)
    set.insert(s, 5, f)
    
    print(set.have(s, 10)) -- 判断有无
    print(set.have(s, 1))
    
    for key, value in ipairs(s) do
      print(key, value)
    end
    

      

    table as linked lists

    请参考:https://www.lua.org/pil/11.3.html

    table as queues (队列,先进先出,不做介绍,请参考原文)

    请参考:https://www.lua.org/pil/11.4.html

    参考

    http://blog.51cto.com/rangercyh/1032925

    https://www.lua.org/pil/11.html

  • 相关阅读:
    GoF23种设计模式之己见
    全面阐述某系统设计所实现的质量属性战术
    对XX系统的可用性和易用性改良
    《淘宝网》的质量属性描述
    读《架构漫谈》之后
    软件架构之再理解
    《架构之美》阅读笔记06
    《架构之美》阅读笔记05
    《架构之美》阅读笔记04
    《架构之美》阅读笔记03
  • 原文地址:https://www.cnblogs.com/alexYuin/p/9942842.html
Copyright © 2020-2023  润新知