2011-02-05 47 views
5

Tôi có một mảng x trong Lua. Tôi muốn đặt head = x[1]rest = phần còn lại của mảng, sao cho rest[1] = x[2], rest[2] = x[3], v.v.Đưa phần tử đầu tiên ra khỏi mảng

Làm cách nào để làm điều này?

(lưu ý: Tôi không quan tâm nếu các mảng ban đầu bị biến đổi Trong javascript tôi sẽ làm head = x.shift()x sẽ chứa các yếu tố còn lại..)

Trả lời

12

head = table.remove(x, 1)

"Pop" là một chút một thuật ngữ sai, vì nó ngụ ý một hoạt động giá rẻ, và loại bỏ phần tử đầu tiên của một bảng đòi hỏi phải di chuyển phần còn lại của nội dung - do đó có tên là "shift" trong JavaScript và một số ngôn ngữ khác.

+1

Lưu ý, đối với một mảng có kích thước hợp lý, đây là một hoạt động rất chậm; hãy thử và xem xét lại lý do tại sao bạn muốn thực hiện điều này ... – daurnimator

+3

@daurnimator nghĩa là "mảng _any không hợp lý kích thước" B-) –

+0

Thay vì xem xét lại động lực cho việc này, thay vì xem xét có lẽ sử dụng cấu trúc dữ liệu khác với mảng. Một danh sách liên kết (dễ tạo trong Lua) làm cho hoạt động này rẻ, với chi phí cần nhiều dung lượng hơn cho mỗi nút. – Phrogz

3

Bạn muốn table.remove:

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

Như @daurnimator chỉ ra, điều này đòi hỏi rất nhiều nỗ lực bởi việc thực hiện cơ bản của mảng trong thời gian chạy Lua, chuyển tất cả các yếu tố bảng. Nếu bạn thay vì có thể đại diện cho mảng của bạn về phía sau, gọi mục cuối cùng trong mảng head, sau đó cuộc gọi đến table.remove() sẽ là một pop rẻ:

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

Ngoài ra, bạn có thể chọn để đại diện cho chuỗi lại các yếu tố như một linked list . Trong trường hợp này, popping một mục khỏi người đứng đầu danh sách cũng là một hoạt động rẻ (nhưng đẩy một vào cuối cùng không phải là, trừ khi bạn theo dõi các 'đuôi' trong danh sách của bạn):

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 

Note đặc biệt là

không sửa đổi bất kỳ cấu trúc dữ liệu nhưng chỉ mang đến cho bạn một tay cầm rest trên một liên kết cụ thể trong chuỗi.

Các vấn đề liên quan