【问题标题】:Popping the first element off an array in Lua弹出数组的第一个元素
【发布时间】:2011-06-22 01:50:38
【问题描述】:

我在 Lua 中有一个数组 x。我想设置head = x[1]rest = 数组的其余部分,以便rest[1] = x[2]rest[2] = x[3]

我该怎么做?

(注意:我不在乎原始数组是否发生了变异。在 Javascript 中,我会执行 head = x.shift()x 将包含剩余的元素。)

【问题讨论】:

    标签: arrays lua lua-table


    【解决方案1】:

    head = table.remove(x, 1)

    “Pop”有点用词不当,因为它意味着一种廉价的操作,并且删除表格的第一个元素需要重新定位其余的内容——因此在 JavaScript 和其他一些语言中称为“shift”。

    【讨论】:

    • 注意,对于任何合理大小的数组,这是一个非常慢的操作;试着重新考虑你为什么要这样做......
    • @daurnimator 你的意思是“任何不合理大小的数组”B-)
    • 与其重新考虑这样做的动机,不如考虑使用数组以外的数据结构。一个链表(在 Lua 中很容易创建)使得这个操作成本很低,但代价是每个节点需要更多的存储空间。
    【解决方案2】:

    你想要table.remove:

    local t = {1,2,3,4}
    local head = table.remove(t,1)
    print( head )
    --> 1
    print( #t )
    --> 3
    print( t[1] )
    --> 2
    

    正如@daurnimator 所指出的,这需要Lua 运行时中数组的底层实现付出很多努力,移动所有的表格元素。如果你可以反过来表示你的数组,调用数组中的最后一项head,那么对table.remove()的调用将是一个廉价的流行:

    local t = {4,3,2,1}
    local head = table.remove(t)
    print(head)
    --> 1
    print( #t )
    --> 3
    print( t[#t] )
    --> 2
    

    或者,您可以选择将您的元素序列表示为linked list。在这种情况下,从列表头部弹出一个项目也是一种廉价的操作(但将一个项目推到末尾不是,除非您跟踪列表中的“尾部”):

    local setm,getm = setmetatable,getmetatable
    local linkedlist=setm({__index={
      tail = function(l) while l.rest do l=l.rest end return l end, -- N.B. O(n)!
      push = function(l,v,t) t=l:tail() t.rest=setm({val=v},getm(l)) return t end,
      cram = function(l,v) return setm({val=v,rest=l},getm(l)) end,
      each = function(l,v)
        return function() if l then v,l=l.val,l.rest return v end end
      end
    }},{ __call=function(lmeta,v,...)
      local head,tail=setm({val=v},lmeta) tail=head
      for i,v in ipairs{...} do tail=tail:push(v) end
      return head
    end })
    
    local numbers = linkedlist(1,2,3,4)
    for n in numbers:each() do print(n) end
    --> 1
    --> 2
    --> 3
    --> 4
    
    local head,rest = numbers.val, numbers.rest
    print(head)
    --> 1
    
    for n in rest:each() do print(n) end
    --> 2
    --> 3
    --> 4
    
    local unrest = rest:cram('99')
    for n in unrest:each() do print(n) end
    --> 99
    --> 2
    --> 3
    --> 4
    

    特别注意

    local head,rest = numbers.val, numbers.rest
    

    不修改任何数据结构,而只是在链中的特定链接上为您提供rest 句柄。

    【讨论】:

      【解决方案3】:

      通常在 Lua 中将元素 x 插入序列中的操作...

      例如:S={a,b,c,d,e,f} 到 S={a,b,c,x,d,e,f}

      ...非常耗时,因为 d 必须移动到索引 5,e 移动到索引 6 等等。

      是否存在其他形式 S 的序列,其中 S[a]=b, S[b]=c,S[c]=d,S[d]=e 和 S[e]=f?这样,您所要做的就是输入:

      S[c]=x S[x]=d

      boom,x 仅在两次操作中位于 c 之后和 d 之前。

      【讨论】:

      • 最近发现我说的这个叫“链表”。
      猜你喜欢
      • 1970-01-01
      • 2019-10-04
      • 2018-12-24
      • 2021-01-31
      • 2016-12-30
      • 1970-01-01
      • 2022-11-16
      • 2020-03-19
      • 1970-01-01
      相关资源
      最近更新 更多