X-Git-Url: https://git.enpas.org/?a=blobdiff_plain;f=util%2Farray.lua;h=9bf215af72c9d73b0b09e1fb31ccaf95fa8a6f4a;hb=bd602f6c077112e2f0c9125ad9cc6dd646322fec;hp=ae3a0b5bdf178f247356e093eef15c512a56f64b;hpb=4ac119e7af89cd0003f32427b69314bec147ecb6;p=prosody.git diff --git a/util/array.lua b/util/array.lua index ae3a0b5b..9bf215af 100644 --- a/util/array.lua +++ b/util/array.lua @@ -1,20 +1,28 @@ -- Prosody IM --- Copyright (C) 2008-2009 Matthew Wild --- Copyright (C) 2008-2009 Waqas Hussain --- +-- Copyright (C) 2008-2010 Matthew Wild +-- Copyright (C) 2008-2010 Waqas Hussain +-- -- This project is MIT/X11 licensed. Please see the -- COPYING file in the source package for more information. -- -local t_insert, t_sort, t_remove, t_concat - = table.insert, table.sort, table.remove, table.concat; +local t_insert, t_sort, t_remove, t_concat + = table.insert, table.sort, table.remove, table.concat; + +local setmetatable = setmetatable; +local math_random = math.random; +local pairs, ipairs = pairs, ipairs; +local tostring = tostring; local array = {}; local array_base = {}; local array_methods = {}; -local array_mt = { __index = array_methods, __tostring = function (array) return array:concat(", "); end }; +local array_mt = { __index = array_methods, __tostring = function (array) return "{"..array:concat(", ").."}"; end }; -local function new_array(_, t) +local function new_array(self, t, _s, _var) + if type(t) == "function" then -- Assume iterator + t = self.collect(t, _s, _var); + end return setmetatable(t or {}, array_mt); end @@ -25,6 +33,15 @@ end setmetatable(array, { __call = new_array }); +-- Read-only methods +function array_methods:random() + return self[math_random(1,#self)]; +end + +-- These methods can be called two ways: +-- array.method(existing_array, [params [, ...]]) -- Create new array for result +-- existing_array:method([params, ...]) -- Transform existing array into result +-- function array_base.map(outa, ina, func) for k,v in ipairs(ina) do outa[k] = func(v); @@ -33,11 +50,22 @@ function array_base.map(outa, ina, func) end function array_base.filter(outa, ina, func) - for k,v in ipairs(ina) do + local inplace, start_length = ina == outa, #ina; + local write = 1; + for read=1,start_length do + local v = ina[read]; if func(v) then - outa:push(v); + outa[write] = v; + write = write + 1; + end + end + + if inplace and write <= start_length then + for i=write,start_length do + outa[i] = nil; end end + return outa; end @@ -49,15 +77,18 @@ function array_base.sort(outa, ina, ...) return outa; end ---- These methods only mutate -function array_methods:random() - return self[math.random(1,#self)]; +function array_base.pluck(outa, ina, key) + for i=1,#ina do + outa[i] = ina[i][key]; + end + return outa; end +--- These methods only mutate the array function array_methods:shuffle(outa, ina) local len = #self; for i=1,#self do - local r = math.random(i,len); + local r = math_random(i,len); self[i], self[r] = self[r], self[i]; end return self; @@ -80,18 +111,32 @@ function array_methods:append(array) return self; end -array_methods.push = table.insert; -array_methods.pop = table.remove; -array_methods.concat = table.concat; -array_methods.length = function (t) return #t; end +function array_methods:push(x) + t_insert(self, x); + return self; +end + +function array_methods:pop(x) + local v = self[x]; + t_remove(self, x); + return v; +end + +function array_methods:concat(sep) + return t_concat(array.map(self, tostring), sep); +end + +function array_methods:length() + return #self; +end --- These methods always create a new array function array.collect(f, s, var) - local t, var = {}; + local t = {}; while true do var = f(s, var); if var == nil then break; end - table.insert(t, var); + t_insert(t, var); end return setmetatable(t, array_mt); end @@ -100,7 +145,6 @@ end -- Setup methods from array_base for method, f in pairs(array_base) do - local method = method; -- Yes, this is necessary :) local base_method = f; -- Setup global array method which makes new array array[method] = function (old_a, ...)