Mercurial > prosody-hg
comparison util/array.lua @ 1918:dd35d07d673f
util.array: Per-array methods now always mutate the array, array.* return a mutated copy, and most methods (e.g. sort) now return the array
| author | Matthew Wild <mwild1@gmail.com> |
|---|---|
| date | Mon, 05 Oct 2009 14:38:04 +0100 |
| parents | 569d58d21612 |
| children | e9d5406caf8c |
comparison
equal
deleted
inserted
replaced
| 1917:ac5fca9ef6fe | 1918:dd35d07d673f |
|---|---|
| 4 -- | 4 -- |
| 5 -- This project is MIT/X11 licensed. Please see the | 5 -- This project is MIT/X11 licensed. Please see the |
| 6 -- COPYING file in the source package for more information. | 6 -- COPYING file in the source package for more information. |
| 7 -- | 7 -- |
| 8 | 8 |
| 9 local t_insert, t_sort, t_remove, t_concat | |
| 10 = table.insert, table.sort, table.remove, table.concat; | |
| 11 | |
| 9 local array = {}; | 12 local array = {}; |
| 13 local array_base = {}; | |
| 14 local array_methods = {}; | |
| 15 local array_mt = { __index = array_methods, __tostring = function (array) return array:concat(", "); end }; | |
| 10 | 16 |
| 11 local array_mt = { __index = array, __tostring = function (array) return array:concat(", "); end }; | |
| 12 local function new_array(_, t) | 17 local function new_array(_, t) |
| 13 return setmetatable(t or {}, array_mt); | 18 return setmetatable(t or {}, array_mt); |
| 14 end | 19 end |
| 15 | 20 |
| 16 function array_mt.__add(a1, a2) | 21 function array_mt.__add(a1, a2) |
| 18 return res:append(a1):append(a2); | 23 return res:append(a1):append(a2); |
| 19 end | 24 end |
| 20 | 25 |
| 21 setmetatable(array, { __call = new_array }); | 26 setmetatable(array, { __call = new_array }); |
| 22 | 27 |
| 23 function array:map(func, t2) | 28 function array_base.map(outa, ina, func) |
| 24 local t2 = t2 or array{}; | 29 for k,v in ipairs(ina) do |
| 25 for k,v in ipairs(self) do | 30 outa[k] = func(v); |
| 26 t2[k] = func(v); | |
| 27 end | 31 end |
| 28 return t2; | 32 return outa; |
| 29 end | 33 end |
| 30 | 34 |
| 31 function array:filter(func, t2) | 35 function array_base.filter(outa, ina, func) |
| 32 local t2 = t2 or array{}; | 36 for k,v in ipairs(ina) do |
| 33 for k,v in ipairs(self) do | |
| 34 if func(v) then | 37 if func(v) then |
| 35 t2:push(v); | 38 outa:push(v); |
| 36 end | 39 end |
| 37 end | 40 end |
| 38 return t2; | 41 return outa; |
| 39 end | 42 end |
| 40 | 43 |
| 44 function array_base.sort(outa, ina, ...) | |
| 45 if ina ~= outa then | |
| 46 outa:append(ina); | |
| 47 end | |
| 48 t_sort(outa, ...); | |
| 49 return outa; | |
| 50 end | |
| 41 | 51 |
| 42 array.push = table.insert; | 52 --- These methods only mutate |
| 43 array.pop = table.remove; | 53 function array_methods:random() |
| 44 array.sort = table.sort; | |
| 45 array.concat = table.concat; | |
| 46 array.length = function (t) return #t; end | |
| 47 | |
| 48 function array:random() | |
| 49 return self[math.random(1,#self)]; | 54 return self[math.random(1,#self)]; |
| 50 end | 55 end |
| 51 | 56 |
| 52 function array:shuffle() | 57 function array_methods:shuffle(outa, ina) |
| 53 local len = #self; | 58 local len = #self; |
| 54 for i=1,#self do | 59 for i=1,#self do |
| 55 local r = math.random(i,len); | 60 local r = math.random(i,len); |
| 56 self[i], self[r] = self[r], self[i]; | 61 self[i], self[r] = self[r], self[i]; |
| 57 end | 62 end |
| 58 return self; | 63 return self; |
| 59 end | 64 end |
| 60 | 65 |
| 61 function array:reverse() | 66 function array_methods:reverse() |
| 62 local len = #self-1; | 67 local len = #self-1; |
| 63 for i=len,1,-1 do | 68 for i=len,1,-1 do |
| 64 self:push(self[i]); | 69 self:push(self[i]); |
| 65 self:pop(i); | 70 self:pop(i); |
| 66 end | 71 end |
| 67 return self; | 72 return self; |
| 68 end | 73 end |
| 69 | 74 |
| 70 function array:append(array) | 75 function array_methods:append(array) |
| 71 local len,len2 = #self, #array; | 76 local len,len2 = #self, #array; |
| 72 for i=1,len2 do | 77 for i=1,len2 do |
| 73 self[len+i] = array[i]; | 78 self[len+i] = array[i]; |
| 74 end | 79 end |
| 75 return self; | 80 return self; |
| 76 end | 81 end |
| 77 | 82 |
| 83 array_methods.push = table.insert; | |
| 84 array_methods.pop = table.remove; | |
| 85 array_methods.concat = table.concat; | |
| 86 array_methods.length = function (t) return #t; end | |
| 87 | |
| 88 --- These methods always create a new array | |
| 78 function array.collect(f, s, var) | 89 function array.collect(f, s, var) |
| 79 local t, var = {}; | 90 local t, var = {}; |
| 80 while true do | 91 while true do |
| 81 var = f(s, var); | 92 var = f(s, var); |
| 82 if var == nil then break; end | 93 if var == nil then break; end |
| 83 table.insert(t, var); | 94 table.insert(t, var); |
| 84 end | 95 end |
| 85 return setmetatable(t, array_mt); | 96 return setmetatable(t, array_mt); |
| 86 end | 97 end |
| 87 | 98 |
| 99 --- | |
| 100 | |
| 101 -- Setup methods from array_base | |
| 102 for method, f in pairs(array_base) do | |
| 103 local method = method; -- Yes, this is necessary :) | |
| 104 local base_method = f; | |
| 105 -- Setup global array method which makes new array | |
| 106 array[method] = function (old_a, ...) | |
| 107 local a = new_array(); | |
| 108 return base_method(a, old_a, ...); | |
| 109 end | |
| 110 -- Setup per-array (mutating) method | |
| 111 array_methods[method] = function (self, ...) | |
| 112 return base_method(self, self, ...); | |
| 113 end | |
| 114 end | |
| 115 | |
| 88 _G.array = array; | 116 _G.array = array; |
| 89 module("array"); | 117 module("array"); |
| 90 | 118 |
| 91 return array; | 119 return array; |
