数组列表 list

# 在table的基础山增加了更直观的列表操作函数,同时使用了_count来跟踪元素数量

local list = {}
list.__cname = "util.list"

local null = {}
list.null = null

list.__newindex = function(self, k, v)
    if "number" == type(k) then
        error(string.format("use list:Add to add new index: %s", k))
    end
    rawset(self, k, v)
end

list.__index = list

local function Swap(tb, index1, index2)
    local temp = tb[index1]
    tb[index1] = tb[index2]
    tb[index2] = temp
end

function list.new()
    local obj = {}
    setmetatable(obj, list)
    obj:ctor()
    return obj
end

function list.attach(arrTb)
    setmetatable(arrTb, list)
    arrTb._count = #arrTb
    arrTb._ver = 0
end

function list:ctor()
    self._count = 0
    self._ver = 0
end

function list:_IcrVersion()
    self._ver = self._ver + 1
end

function list:Clear()
    if 0 == self._count then return end
    for i=1,self._count do
        self[i] = nil
    end
    self._count = 0
    self:_IcrVersion()
end

function list:GetCount()
    return self._count
end

function list:Add(v)
    if nil == v then v = null end

    self._count = self._count + 1
    rawset(self, self._count, v) --self[self._count] = v
    self:_IcrVersion()
end

function list:Set(index, v)
    if nil == v then v = null end
    if index > self._count then return end
    self[index] = v
    self:_IcrVersion()
end

function list:InsertAt(index, v)
    local count_1 = self._count + 1
    if index < 1 or index > count_1 then return end

    if nil == v then v = null end
    if index == count_1 then
        self._count = self._count + 1
        rawset(self, self._count, v)
    else
        for i=self._count,index,-1 do --往后移动
            self[i+1] = self[i]
        end
        rawset(self, index, v)
        self._count = self._count + 1
    end
    self:_IcrVersion()
end

function list:GetAt(index)
    --if index < 1 or index > self._count then return nil end
    return self[index]
end

function list:RemoveAt(index)
    if index < 1 or index > self._count then return false end

    local oldValue = self[index]
    if index == self._count then
        self[index] = nil
    else
        for i=index,self._count-1 do --往前移动
            self[i] = self[i+1]
        end
        self[self._count] = nil
    end
    self._count = self._count - 1
    self:_IcrVersion()
    return true, oldValue
end

function list:RemoveRange(index, count)
    if index < 1 or index > self._count then return false end
    local index2 = index + count

    if index2 > self._count then --删除尾部n个元素
        for i=index,self._count do
            self[i] = nil
        end
        self._count = index - 1
    else
        local i = index
        for j=index2,self._count do --往前移动
            self[i] = self[j]
            i = i + 1
        end
        for j=i,self._count do --移掉的置为nil
            self[j] = nil
        end
        self._count = self._count - count
    end
    self:_IcrVersion()
    return true
end

function list:Remove(v)
    local index = self:IndexOf(v)
    if index > 0 then
        self:RemoveAt(index)
        return true
    end
    return false
end

function list:Contains(v)
    return self:IndexOf(v) > 0
end

function list:IndexOf(v)
    if self._count < 1 then return -1 end
    for i=1,self._count do
        if self[i] == v then
            return i
        end
    end
    return -1
end

function list:Find(matchFunc)
    if self._count < 1 then return -1, nil end
    for i=1,self._count do
        local item = self[i]
        if matchFunc(i, item) then
            return i, item
        end
    end
    return -1, nil
end

function list:LastIndexOf(v)
    if self._count < 1 then return -1 end
    for i=self._count,1,-1 do
        if self[i] == v then
            return i
        end
    end
    return -1
end

function list:FindLast(matchFunc)
    if self._count < 1 then return -1, nil end
    for i=self._count,1,-1 do
        local item = self[i]
        if matchFunc(i, item) then
            return i, item
        end
    end
    return -1, nil
end

function list:Sort(func)
    if self._count < 1 then return end
    table.sort(self.arr, func)
    self:_IcrVersion()
end

function list:Reverse()
    if self._count < 2 then return end
    local i = 1
    local j = self._count
    while i < j do
        Swap(self, i, j)
        i = i + 1
        j = j - 1
    end
    self:_IcrVersion()
end

function list:Shuffle()
    local count = self._count
    if 1 == count then return end
    local arr = self
    for i=1,count do
        local r = math.random(count)
        local temp = arr[i]
        arr[i] = arr[r]
        arr[r] = temp
    end
    self:_IcrVersion()
end

function list:__tostring()
    if 0 == self._count then return "" end
    local strTb = {}
    for i=1,self._count do
        table.insert(strTb, tostring(self[i]))
    end
    return table.concat(strTb, ",")
end

function list:pairs()
    error("use list:ipairs")
end

function list:ipairs()
    local iteratorCur = 1
    local version = self._ver
    local function iterator(tb, key)
        if version ~= self._ver then error("list modified in Iterator") end

        if iteratorCur > self._count then return nil end
        local k = iteratorCur
        iteratorCur = iteratorCur + 1
        return k, self[k]
    end
    return iterator
end

function list:IsReadOnly()
    return false
end

return list

 

posted @ 2021-11-12 00:26  yanghui01  阅读(47)  评论(0编辑  收藏  举报