2 -- Copyright (C) 2008-2010 Matthew Wild
3 -- Copyright (C) 2008-2010 Waqas Hussain
5 -- This project is MIT/X11 licensed. Please see the
6 -- COPYING file in the source package for more information.
9 local t_insert
, t_sort
, t_remove
, t_concat
10 = table.insert
, table.sort, table.remove, table.concat
;
12 local setmetatable
= setmetatable
;
13 local math_random
= math
.random;
14 local math_floor
= math
.floor;
15 local pairs
, ipairs
= pairs
, ipairs
;
16 local tostring = tostring;
20 local array_base
= {};
21 local array_methods
= {};
23 __index
= array_methods
;
25 __tostring
= function (self
) return "{"..self
:concat(", ").."}"; end;
28 function array_mt
:__freeze() return self
; end
30 local function new_array(self
, t
, _s
, _var
)
31 if type(t
) == "function" then -- Assume iterator
32 t
= self
.collect(t
, _s
, _var
);
34 return setmetatable(t
or {}, array_mt
);
37 function array_mt
.__add(a1
, a2
)
38 local res
= new_array();
39 return res
:append(a1
):append(a2
);
42 function array_mt
.__eq(a
, b
)
55 function array_mt
.__div(a1
, func
)
56 local a2
= new_array();
59 local new_value
= func(a1
[i
]);
60 if new_value
~= nil then
68 setmetatable(array
, { __call
= new_array
});
71 function array_methods
:random()
72 return self
[math_random(1, #self
)];
75 -- Return a random value excluding the one at idx
76 function array_methods
:random_other(idx
)
78 return self
[((math
.random(1, max-1)+(idx
-1))%max)+1];
81 -- These methods can be called two ways:
82 -- array.method(existing_array, [params [, ...]]) -- Create new array for result
83 -- existing_array:method([params, ...]) -- Transform existing array into result
85 function array_base
.map(outa
, ina
, func
)
86 for k
, v
in ipairs(ina
) do
92 function array_base
.filter(outa
, ina
, func
)
93 local inplace
, start_length
= ina
== outa
, #ina
;
95 for read = 1, start_length
do
103 if inplace
and write <= start_length
then
104 for i
= write, start_length
do
112 function array_base
.sort(outa
, ina
, ...)
120 function array_base
.unique(outa
, ina
)
122 return array_base
.filter(outa
, ina
, function (item
)
132 function array_base
.pluck(outa
, ina
, key
)
134 outa
[i
] = ina
[i
][key
];
139 function array_base
.reverse(outa
, ina
)
142 local middle
= math_floor(len
/2);
147 outa
[i
], outa
[o
] = outa
[o
], outa
[i
];
152 outa
[i
] = ina
[off
- i
];
158 --- These methods only mutate the array
159 function array_methods
:shuffle()
162 local r
= math_random(i
, len
);
163 self
[i
], self
[r
] = self
[r
], self
[i
];
168 function array_methods
:append(ina
)
169 local len
, len2
= #self
, #ina
;
171 self
[len
+i
] = ina
[i
];
176 function array_methods
:push(x
)
181 array_methods
.pop
= t_remove
;
183 function array_methods
:concat(sep
)
184 return t_concat(array
.map(self
, tostring), sep
);
187 function array_methods
:length()
191 --- These methods always create a new array
192 function array
.collect(f
, s
, var
)
196 if var
== nil then break; end
199 return setmetatable(t
, array_mt
);
204 -- Setup methods from array_base
205 for method
, f
in pairs(array_base
) do
206 local base_method
= f
;
207 -- Setup global array method which makes new array
208 array
[method
] = function (old_a
, ...)
209 local a
= new_array();
210 return base_method(a
, old_a
, ...);
212 -- Setup per-array (mutating) method
213 array_methods
[method
] = function (self
, ...)
214 return base_method(self
, self
, ...);