Commit 28cba4dd authored by nanahira's avatar nanahira

new

parent cc0dc5dd
---
-- lodash for lua
-- @module lodash
-- @author Daniel Moghimi (daniel.mogimi@gmail.com)
-- @license MIT
_ = {
_VERSION = '0.02'
}
if type(table.pack) ~= 'function' then
function table.pack(...)
return { n = select("#", ...), ... }
end
end
if type(table.unpack) ~= 'function' then
table.unpack = unpack
end
--- Array
-- @section Array
---
-- Creates an array of elements split into groups the length of size.
-- If collection can’t be split evenly, the final chunk will be the
-- remaining elements.
-- @usage local t = _.chunk({'x', 'y', 'z', 1, 2, 3, 4, true , false}, 4)
-- _.print(t)
-- --> {{"x", "y", "z", 1}, {2, 3, 4, true}, {false}}
--
-- @param array The array to process.
-- @param[opt=1] size The length of each chunk.
-- @return the new array containing chunks.
_.chunk = function (array, size)
local t = {}
local size = size == 0 and 1 or size or 1
local c, i = 1, 1
while true do
t[i] = {}
for j = 1, size do
_.push(t[i], array[c])
c = c + 1
end
if _.gt(c, #array) then
break
end
i = i + 1
end
return t
end
---
-- Creates an array with all falsey values removed. The values false,
-- nil are falsey.
-- @usage local t = _.compact({'x', 'y', nil, 1, 2, 3, false, true , false})
-- _.print(t)
-- --> {"x", "y", 1, 2, 3, true}
--
-- @param array The array to compact
-- @return Returns the new array of filtered values
_.compact = function (array)
local t = {}
for k, v in pairs(array) do
if v then
_.push(t, v)
end
end
return t
end
---
-- Creates an array of unique array values not included in the other
-- provided arrays.
-- @usage _.print(_.difference({3, 1, 2, 9, 5, 9}, {4, 5}, {9, 1}))
-- --> {3, 2}
--
-- @param array The array to inspect.
-- @param ... The arrays of values to exclude.
-- @return Returns the new array of filtered values.
_.difference = function (array, ...)
local t = {}
local c = 1
local tmp = _.table(...)
for k, v in ipairs(array) do
while not _.isNil(tmp[c]) do
for j, v2 in ipairs(tmp[c]) do
if v == v2 then goto doubleBreak end
end
c = c + 1
end
_.push(t, v)
::doubleBreak::
c = 1
end
return t
end
---
-- Creates a slice of array with n elements dropped from the beginning.
-- @usage _.print(_.drop({1, 2, 3, 4, 5, 6}, 2))
-- --> {3, 4, 5, 6}
--
-- @param array The array to query.
-- @param[opt=1] n The number of elements to drop.
-- @return Returns the slice of array.
_.drop = function (array, n)
local n = n or 1
return _.slice(array, n + 1)
end
local callIteratee = function (predicate, selfArg, ...)
local result
local predicate = predicate or _.identity
if selfArg then
result = predicate(selfArg, ...)
else
result = predicate(...)
end
return result
end
---
-- Creates a slice of array with n elements dropped from the end.
-- @usage _.print(_.dropRight({1, 2, 3, 4, 5, 6}, 2))
-- --> {1, 2, 3, 4}
--
-- @param array The array to query.
-- @param[opt=1] n The number of elements to drop.
-- @return Returns the slice of array.
_.dropRight = function (array, n)
local n = n or 1
return _.slice(array, nil, #array - n)
end
local dropWhile = function(array, predicate, selfArg, start, step, right)
local t = {}
local c = start
while not _.isNil(array[c]) do
::cont::
if #t == 0 and
callIteratee(predicate, selfArg, array[c], c, array) then
c = c + step
goto cont
end
if right then
_.enqueue(t, array[c])
else
_.push(t, array[c])
end
c = c + step
end
return t
end
---
-- Creates a slice of array excluding elements dropped from the end.
-- Elements are dropped until predicate returns falsey.
-- @usage _.print(_.dropRightWhile({1, 5, 2, 3, 4, 5, 4, 4}, function(n)
-- return n > 3
-- end))
-- --> {1, 5, 2, 3}
--
-- @param array The array to query.
-- @param[opt=_.identity] predicate The function to invoked per iteratin.
-- @param[opt] selfArg The self binding of predicate.
-- @return Return the slice of array.
_.dropRightWhile = function(array, predicate, selfArg)
return dropWhile(array, predicate, selfArg, #array, -1, true)
end
---
-- Creates a slice of array excluding elements dropped from the beginning.
-- Elements are dropped until predicate returns falsey.
-- @usage _.print(_.dropWhile({1, 2, 2, 3, 4, 5, 4, 4, 2}, function(n)
-- return n < 3
-- end))
-- --> {3, 4, 5, 4, 4, 2}
--
-- @param array The array to query.
-- @param[opt=_.idenitity] predicate The function invoked per iteration.
-- @param[opt] selfArg The self binding of predicate.
-- @return Return the slice of array.
_.dropWhile = function(array, predicate, selfArg)
return dropWhile(array, predicate, selfArg, 1, 1)
end
_.enqueue = function (array, value)
return table.insert(array, 1, value)
end
---
-- Fills elements of array with value from start up to, including, end.
-- @usage local array = {1, 2, 3, 4}
-- _.fill(array, 'x', 2, 3)
-- _.print(array)
-- --> {1, "x", "x", 4}
--
-- @param array The array to fill.
-- @param value The value to fill array with.
-- @param[opt=1] start The start position.
-- @param[opt=#array] stop The end position.
-- @return Returns array.
_.fill = function (array, value, start, stop)
local start = start or 1
local stop = stop or #array
for i=start, stop, start > stop and -1 or 1 do
array[i] = value
end
return array
end
local findIndex = function(array, predicate, selfArg, start, step)
local c = start
while not _.isNil(array[c]) do
if callIteratee(predicate, selfArg, array[c], c, array) then
return c
end
c = c + step
end
return -1
end
---
-- This method is like [_.find](#_.find) except that it returns the index of the
-- first element predicate returns truthy for instead of the element itself.
-- @usage _.print(_.findIndex({{a = 1}, {a = 2}, {a = 3}, {a = 2}, {a = 3}}, function(v)
-- return v.a == 3
-- end))
-- --> 3
--
-- @param array The array to search.
-- @param[opt=_.idenitity] predicate The function invoked per iteration.
-- @param[opt] selfArg The self binding of predicate.
-- @return Returns the index of the found element, else -1.
_.findIndex = function (array, predicate, selfArg)
return findIndex(array, predicate, selfArg, 1, 1)
end
---
-- This method is like [_.findIndex](#_.findIndex) except that it iterates over
-- elements of collection from right to left.
-- @usage _.print(_.findLastIndex({{a = 1}, {a = 2}, {a = 3}, {a = 2}, {a = 3}}, function(v)
-- return v.a == 3
-- end))
-- --> 5
--
-- @param array The array to search.
-- @param[opt=_.idenitity] predicate The function invoked per iteration.
-- @param[opt] selfArg The self binding of predicate.
-- @return Returns the index of the found element, else -1.
_.findLastIndex = function (array, predicate, selfArg)
return findIndex(array, predicate, selfArg, #array, -1)
end
---
-- Gets the first element of array.
-- @usage _.print(_.first({'w', 'x', 'y', 'z'}))
-- --> w
--
-- @param array The array to query.
-- @return Returns the first element of array.
_.first = function (array)
return array[1]
end
---
-- Flattens a nested array.
-- If isDeep is true the array is recursively flattened, otherwise
-- it’s only flattened a single level.
-- @usage _.print(_.flatten({1, 2, {3, 4, {5, 6}}}))
-- --> {1, 2, 3, 4, {5, 6}}
-- _.print(_.flatten({1, 2, {3, 4, {5, 6}}}, true))
-- --> {1, 2, 3, 4, 5, 6}
--
-- @param array The array to flatten.
-- @param isDeep Specify a deep flatten
-- @return Returns the new flattened array.
_.flatten = function(array, isDeep)
local t = {}
for k, v in ipairs(array) do
if _.isTable(v) then
local childeren
if isDeep then
childeren = _.flatten(v)
else
childeren = v
end
for k2, v2 in ipairs(childeren) do
_.push(t, v2)
end
else
_.push(t, v)
end
end
return t
end
---
-- Recursively flattens a nested array.
-- @usage _.print(_.flattenDeep({1, 2, {3, 4, {5, 6}}}))
-- --> {1, 2, 3, 4, 5, 6}
--
-- @param array The array to flatten.
-- @return Returns the new flattened array.
_.flattenDeep = function (array)
return _.flatten(array, true)
end
---
-- Gets the index at which the first occurrence of value is found in array.
-- @usage _.print(_.indexOf({2, 3, 'x', 4}, 'x'))
-- --> 3
--
-- @param array The array to search.
-- @param value The value to search for.
-- @param[opt=1] fromIndex The index to search from.
-- @return Returns the index of the matched value, else -1.
_.indexOf = function (array, value, fromIndex)
return _.findIndex(array, function(n)
return n == value
end)
end
--
---
-- Gets all but the last element of array.
-- @usage _.print(_.initial({1, 2, 3, 'a'}))
-- --> {1, 2, 3}
--
-- @param array The array to query.
-- @return Returns the slice of array.
_.initial = function (array)
return _.slice(array, nil, #array - 1)
end
--
---
-- Creates an array of unique values that are included in all of the
-- provided arrays.
-- @usage _.print(_.intersection({1, 2}, {4, 2}, {2, 1}))
-- --> {2}
--
-- @param The arrays to inspect.
-- @return Returns the new array of shared values.
_.intersection = function (...)
local tmp = _.table(...)
local first = table.remove(tmp, 1)
local t = {}
for i, v in ipairs(first) do
local notFound = false
for i2, v2 in ipairs(tmp) do
if _.indexOf(v2, v) == -1 then
notFound = true
break
end
end
if not notFound then
_.push(t, v)
end
end
return t
-- body
end
---
-- Gets the last element of array.
-- @usage _.print(_.last({'w', 'x', 'y', 'z'}))
-- --> z
--
-- @param array The array to query.
-- @return Returns the last element of array.
_.last = function(array)
return array[#array]
end
---
-- This method is like [_.indexOf](#_.indexOf) except that it iterates
-- over elements of array from right to left.
-- @usage _.print(_.lastIndexOf({2, 3, 'x', 4, 'x', 5}, 'x'))
-- --> 5
--
-- @param array The array to search.
-- @param value The value to search for.
-- @param[opt=#array] fromIndex The index to search from.
-- @return Returns the index of the matched value, else -1.
_.lastIndexOf = function (array, value, fromIndex)
return _.findLastIndex(array, function(n)
return n == value
end)
end
---
-- Removes all provided values from array.
-- @usage local array = {1, 2, 3, 4, 5, 4, 1, 2, 3}
-- _.pull(array, 2, 3)
-- _.print(array)
-- --> {1, 4, 5, 4, 1}
-- @param array The array to modify.
-- @param ... The values to remove.
-- @return Returns array
_.pull = function(array, ...)
local i = 1
while not _.isNil(array[i]) do
for k, v in ipairs(_.table(...)) do
if array[i] == v then
table.remove(array, i)
goto cont
end
end
i = i + 1
::cont::
end
return array
end
_.push = function (array, value)
return table.insert(array, value)
end
---
-- Removes elements from array corresponding to the given indexes and
-- returns an array of the removed elements. Indexes may be specified
-- as an array of indexes or as individual arguments.
-- @usage local array = {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'}
-- local t = _.pullAt(array, 4, 9, 8)
-- _.print(array)
-- --> {"a", "b", "c", "e", "f", "g", "j"}
-- _.print(t)
-- --> {"d", "h", "i"}
--
-- @param array The array to modify.
-- @param ... The indexes of elements to remove
-- @return Returns the new array of removed elements.
_.pullAt = function (array, ...)
local t = {}
local tmp = _.table(...)
table.sort(tmp, function(a, b)
return _.gt(a, b)
end)
for i, index in ipairs(tmp) do
_.enqueue(t, table.remove(array, index))
end
return t
end
---
-- Removes all elements from array that predicate returns truthy for
-- and returns an array of the removed elements.
-- @usage local array = {1, 2, 3, 4, 5, 6, 7, 1, 2, 3, 4, 5, 6, 1, 2, 3, 5, 4}
-- local t = _.remove(array, function(value)
-- return value > 4
-- end)
-- _.print(array)
-- --> {1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4}
-- _.print(t)
-- --> {5, 6, 7, 5, 6, 5}
--
-- @param array The array to modify.
-- @param predicate The function invoked per iteration.
-- @return Returns the new array of removed elements
_.remove = function(array, predicate)
local t = {}
local c = 1
local predicate = predicate or _.identity
while not _.isNil(array[c]) do
if predicate(array[c], c, array) then
_.push(t, table.remove(array, c))
goto cont
end
c = c + 1
::cont::
end
return t
end
---
-- Gets all but the first element of array.
-- @usage _.print(_.rest({1, 2, 3, 'a'}))
-- --> {2, 3, 'a'}
-- @param array The array to query.
-- @return Returns the slice ofa array.
_.rest = function (array)
return _.slice(array, 2, #array)
end
---
-- Reverses the array so the first element becomes the last, the second
-- element becomes the second to last, and so on.
-- @usage _.print(_.reverse({1, 2, 3, 'a', 'b'}))
-- --> {'b', 'a', 3, 2, 1}
--
-- @param array The array to mutate.
-- @return Returns the new reversed array.
_.reverse = function (array)
local t = {}
for i, v in ipairs(array) do
_.enqueue(t, v)
end
return t
end
---
-- Creates a slice of array from start up to, including, end.
-- @usage _.print(_.slice({1, 2, 3, 4, 5, 6}, 2, 3))
-- --> {2, 3}
--
-- @param array The array to slice.
-- @param[opt=1] start The start position.
-- @param[opt=#array] stop The end position
-- @return Returns the slice of array.
_.slice = function (array, start, stop)
local start = start or 1
local stop = stop or #array
local t = {}
for i=start, stop do
t[i - start + 1] = array[i]
end
return t
end
---
-- Creates a slice of array with n elements taken from the beginning.
-- @usage _.print(_.take({1, 2, 3, 4, 5}, 3))
-- --> {1, 2, 3}
--
-- @param array The array to query.
-- @param[opt=1] n The number of elements to take.
-- @return Returns the slice of array.
_.take = function(array, n)
local n = n or 1
return _.slice(array, 1, n)
end
---
-- Creates a slice of array with n elements taken from the end.
-- @usage _.print(_.takeRight({1, 2, 3, 4, 5}, 3))
-- --> {3, 4, 5}
--
-- @param array The array to query.
-- @param[opt=1] n The number of elements to take.
-- @return Returns the slice of array.
_.takeRight = function (array, n)
local n = n or 1
return _.slice(array, #array - n +1)
end
local takeWhile = function(array, predicate, selfArg, start, step, right)
local t = {}
local c = start
while not _.isNil(array[c]) do
if callIteratee(predicate, selfArg, array[c], c, array) then
if right then
_.enqueue(t, array[c])
else
_.push(t, array[c])
end
else
break
end
c = c + step
end
return t
end
---
-- Creates a slice of array with elements taken from the end. Elements
-- are taken until predicate returns falsey. The predicate is bound to
-- selfArg and invoked with three arguments: (value, index, array).
-- @usage _.print(_.takeRightWhile({1, 2, 3, 4, 5, 6, 7, 8}, function(n)
-- return n > 4
-- end))
-- --> {5, 6, 7, 8}
--
-- @param array The array to query.
-- @param predicate The function invoked per iteration.
-- @param selfArg The self binding of predicate.
_.takeRightWhile = function (array, predicate, selfArg)
return takeWhile(array, predicate, selfArg, #array, -1, true)
end
---
-- Creates an array of unique values, from all of the
-- provided arrays.
-- @usage _.print(_.union({1, 2}, {4, 2}, {2, 1}))
-- --> {1, 2, 4}
--
-- @param ... The arrays to inspect
_.union = function (...)
local tmp = _.table(...)
local t = {}
for i, array in ipairs(tmp) do
for i2, v in ipairs(array) do
if _.indexOf(t, v) == -1 then
_.push(t, v)
end
end
end
return t
end
---
-- Creates a slice of array with elements taken from the beginning. Elements
-- are taken until predicate returns falsey. The predicate is bound to
-- selfArg and invoked with three arguments: (value, index, array).
-- @usage _.print(_.takeWhile({1, 2, 3, 4, 5, 6, 7, 8}, function(n)
-- return n < 5
-- end))
-- --> {1, 2, 3, 4}
--
-- @param array The array to query.
-- @param predicate The function invoked per iteration.
-- @param selfArg The self binding of predicate.
_.takeWhile = function (array, predicate, selfArg)
return takeWhile(array, predicate, selfArg, 1, 1)
end
---
-- Creates a duplicate-free version of an array in which only the first
-- occurence of each element is kept. If an iteratee function is provided
-- it’s invoked for each element in the array to generate the criterion
-- by which uniqueness is computed. The iteratee is bound to thisArg and
-- invoked with three arguments: (value, index, array).
-- @usage _.print(_.uniq({1, 3, 2, 2}))
-- --> {1, 3, 2}
--_.print(_.uniq({{x=1}, {x=2}, {x=2}, {x=3}, {x=1}}, function(n)
-- return n.x
-- end))
-- --> {{["x"]=1}, {["x"]=2}, {["x"]=3}}
--
-- @param array The array to inspect.
-- @param iteratee The function invoked per iteration.
-- @param selfArg The self binding of predicate.
-- @return Returns the new duplicate-value-free array.
_.uniq = function(array, iteratee, selfArg)
local t = {}
local results = {}
for k, v in ipairs(array) do
local r = callIteratee(iteratee, selfArg, v, k, array)
if _.indexOf(results, r) == -1 then
_.push(t, v)
end
_.push(results, r)
end
return t
end
---
-- The inverse of _.pairs; this method returns an object composed from
-- arrays of property names and values. Provide either a single two dimensional
-- array, e.g. [[key1, value1], [key2, value2]] or two arrays, one of
-- property names and one of corresponding values.
-- @usage _.print(_.zipObject({{'fred', 30}, {'alex', 20}}))
-- --> {["alex"]=20, ["fred"]=30}
-- _.print(_.zipObject({'fred', 'alex'}, {30, 20}))
-- --> {["alex"]=20, ["fred"]=30}
--
-- @param ... The properties/values
-- @return Returns the new object.
_.zipObject = function (...)
local tmp = _.table(...)
local t = {}
if #tmp == 1 then
for i, pair in ipairs(tmp[1]) do
t[pair[1]] = pair[2]
end
else
for i = 1, #tmp[1] do
t[tmp[1][i]] = tmp[2][i]
end
end
return t
end
---
-- This method is like [_.zip](#_.zip) except that it accepts an array of grouped
-- elements and creates an array regrouping the elements to their pre-zip
-- configuration.
-- @usage local t = _.zip({'a', 'b', 'c'}, {1, 2, 3}, {10, 20, 30})
-- _.print(t)
-- --> {{"a", 1, 10}, {"b", 2, 20}, {"c", 3, 30}}
-- _.print(_.unzip(t))
-- --> {{"a", "b", "c"}, {1, 2, 3}, {10, 20, 30}}
--
-- @param array The array of grouped elements to process.
-- @return Returns the new array of regrouped elements.
_.unzip = function (array)
return _.zip(_.args(array))
end
---
-- Creates an array excluding all provided values
-- @usage _.print(_.without({1,1, 2, 3, 2, 3, 5, 5, 1, 2}, 5, 1))
-- --> {2, 3, 2, 3, 2}
--
-- @param array The array to filter.
-- @param ... The values to exclude.
-- @return Returns the new array of filtered values.
_.without = function (array, ...)
local t = {}
for i, v in ipairs(array) do
local args = _.table(...)
if _.indexOf(args, v) == -1 then
_.push(t, v)
end
end
return t
end
---
-- Creates an array of grouped elements, the first of which contains
-- the first elements of the given arrays, the second of which contains
-- the second elements of the given arrays, and so on.
-- @usage local t = _.zip({'a', 'b', 'c'}, {1, 2, 3}, {10, 20, 30})
-- _.print(t)
-- --> {{"a", 1, 10}, {"b", 2, 20}, {"c", 3, 30}}
--
-- @param ... The arrays to process
-- @return Returns the new array of grouped elements.
_.zip = function (...)
local t = {}
for i, array in ipairs(_.table(...)) do
for j, v in ipairs(array) do
t[j] = t[j] or {}
t[j][i] = v
end
end
return t
end
--- Collection
-- @section Collection
---
-- Creates an array of elements corresponding to the given keys,
-- or indexes, of collection. Keys may be specified as individual
-- arguments or as arrays of keys.
-- @usage _.print(_.at({'1', '2', '3', '4', a='a', b='b'}, {1, 2}, 'b'))
-- --> {"1", "2", "b"}
--
-- @param collection The collection to iterate over.
-- @param ... The property names or indexes of elements to pick,
-- specified individually or in arrays.
-- @return Return the new array of picked elements.
_.at = function (collection, ...)
local t = {}
for k, key in ipairs(_.table(...)) do
if _.isTable(key) then
for k, key in ipairs(key) do
_.push(t, collection[key])
end
else
_.push(t, collection[key])
end
end
return t
end
---
-- Creates an object composed of keys generated from the results of
-- running each element of collection through iteratee. The corresponding
-- value of each key is the number of times the key was returned by
-- iteratee. The iteratee is bound to selfArg and invoked with three arguments:
-- (value, index|key, collection).
--
-- @usage _.print(_.countBy({4.3, 6.1, 6.4}, function(n)
-- return math.floor(n)
-- end))
-- --> {[4]=1, [6]=2}
--
-- @param collection The collection to iterate over. (table|string)
-- @param[opt=_.identity] iteratee The function invoked per iteration.
-- @param[opt] selfArg The self binding of predicate.
-- @return Returns the composed aggregate object.
_.countBy = function (collection, iteratee, selfArg)
local t = {}
for k, v in _.iter(collection) do
local r = _.str(
callIteratee(iteratee, selfArg, v, k, collection)
)
if _.isNil(t[r]) then
t[r] = 1
else
t[r] = t[r] + 1
end
end
return t
end
---
-- Creates an object composed of keys generated from the results of
-- running each element of collection through iteratee. The corresponding
-- value of each key is an array of the elements responsible for generating
-- the key. The iteratee is bound to selfArg and invoked with three arguments:
-- (value, index|key, collection).
-- @usage _.print(_.groupBy({4.3, 6.1, 6.4}, function(n)
-- return math.floor(n)
-- end))
-- --> {[4]={4.3}, [6]={6.1, 6.4}}
--
-- @param collection The collection to iterate over. (table|string)
-- @param[opt=_.identity] iteratee The function invoked per iteration.
-- @param[opt] selfArg The self binding of predicate.
-- @return Returns the composed aggregate object.
_.groupBy = function (collection, iteratee, selfArg)
local t = {}
for k, v in _.iter(collection) do
local r = _.str(
callIteratee(iteratee, selfArg, v, k, collection)
)
if _.isNil(t[r]) then
t[r] = {v}
else
_.push(t[r], v)
end
end
return t
end
---
-- Creates an object composed of keys generated from the results of
-- running each element of collection through iteratee. The corresponding
-- value of each key is the last element responsible for generating the key.
-- The iteratee function is bound to selfArg and invoked with three arguments:
-- (value, index|key, collection).
-- @usage local keyData = {
-- {dir='l', a=1},
-- {dir='r', a=2}
-- }
-- _.print('40.indexBy :', _.indexBy(keyData, function(n)
-- return n.dir
-- end))
-- --> {["l"]={[a]=1, [dir]="l"}, ["r"]={[a]=2, [dir]="r"}}
--
-- @param collection The collection to iterate over. (table|string)
-- @param[opt=_.identity] iteratee The function invoked per iteration.
-- @param[opt] selfArg The self binding of predicate.
-- @return Returns the composed aggregate object.
_.indexBy = function (collection, iteratee, selfArg)
local t = {}
for k, v in _.iter(collection) do
local r = _.str(
callIteratee(iteratee, selfArg, v, k, collection)
)
t[r] = v
end
return t
end
---
-- Checks if predicate returns truthy for all elements of collection.
-- The predicate is bound to selfArg and invoked with three arguments:
-- (value, index|key, collection).
-- @usage _.print(_.every({1, 2, 3, 4, '5', 6}, _.isNumber))
-- --> false
-- _.print(_.every({1, 2, 3, 4, 5, 6}, _.isNumber))
-- --> true
--
-- @param collection The collection to iterate over. (table|string)
-- @param[opt=_.identity] predicate The function invoked per iteration
-- @param[opt] selfArg The self binding of predicate.
_.every = function (collection, predicate, selfArg)
for k, v in _.iter(collection) do
if not callIteratee(predicate, selfArg, v, k, collection) then
return false
end
end
return true
end
local filter = function(collection, predicate, selfArg, reject)
local t = {}
for k, v in _.iter(collection) do
local check = callIteratee(predicate, selfArg, v, k, collection)
if reject then
if not check then
_.push(t, v)
end
else
if check then
_.push(t, v)
end
end
end
return t
end
---
-- Iterates over elements of collection, returning an array of all
-- elements predicate returns truthy for. The predicate is bound to
-- selfArg and invoked with three arguments: (value, index|key, collection).
-- @usage _.print(_.filter({1, 2, 3, 4, '5', 6, '7'}, _.isNumber))
-- --> {1, 2, 3, 4, 6}
--
-- @param collection The collection to iterate over. (table|string)
-- @param[opt=_.identity] predicate The function invoked per iteration
-- @param[opt] selfArg The self binding of predicate.
_.filter = function (collection, predicate, selfArg)
return filter(collection, predicate, selfArg)
end
---
-- Iterates over elements of collection invoking iteratee for each element.
-- The iteratee is bound to selfArg and invoked with three arguments:
-- (value, index|key, collection). Iteratee functions may exit iteration
-- early by explicitly returning false.
--
-- @param collection The collection to iterate over. (table|string)
-- @param[opt=_.identity] predicate The function invoked per iteration
-- @param[opt] selfArg The self binding of predicate.
-- @return Returns collection.
_.forEach = function (collection, predicate, selfArg)
for k, v in _.iter(collection) do
callIteratee(predicate, selfArg, v, k, collection)
end
return collection
end
---
-- This method is like [_.forEach](#_.forEach) except that it iterates
-- over elements of collection from right to left.
--
-- @param collection The collection to iterate over. (table|string)
-- @param[opt=_.identity] predicate The function invoked per iteration
-- @param[opt] selfArg The self binding of predicate.
-- @return Returns collection.
_.forEachRight = function (collection, predicate, selfArg)
for k, v in _.iterRight(collection) do
callIteratee(predicate, selfArg, v, k, collection)
end
return collection
end
---
-- Checks if target is in collection.
-- @usage print(_.includes({1, 2, 'x', 3, ['5']=4, x=3, 5}, 'x'))
-- --> true
-- print(_.includes({1, 2, 'x', 3, ['5']=4, x=3, 5}, 'z'))
-- --> false
-- @param collection The collection to search
-- @param target The value to search for.
_.includes = function (collection, target)
local result = _.find(collection, function (n)
return n == target
end)
return result ~= nil
end
---
-- Invokes method of each element in collection, returning an array of the
-- results of each invoked method. Any additional arguments are provided
-- to each invoked method. func bound to, each element in collection.
-- @usage _.print(_.invoke({'1.first', '2.second', '3.third'}, string.sub, 1, 1))
-- --> {"1", "2", "3"}
--
-- @param collection The collection to iterate over.
-- @param method The method to invoke per iteration.
-- @param ... The arguments to invoke the method with.
-- @return Returns the array of results.
_.invoke = function (collection, method, ...)
local t = {}
for k, v in _.iter(collection) do
_.push(t, callIteratee(method, v, ...))
end
return t
end
---
-- Creates an array of values by running each element in collection through
-- iteratee. The iteratee is bound to selfArg and invoked with three
-- arguments: (value, index|key, collection).
-- @usage _.print(_.map({1, 2, 3, 4, 5, 6, 7, 8, 9}, function(n)
-- return n * n
-- end))
-- --> {1, 4, 9, 16, 25, 36, 49, 64, 81}
--
-- @param collection The collection to iterate over. (table|string)
-- @param[opt=_.identity] iteratee The function invoked per iteration
-- @param[opt] selfArg The self binding of predicate.
_.map = function (collection, iteratee, selfArg)
local t = {}
for k, v in _.iter(collection) do
t[k] = callIteratee(iteratee, selfArg, v, k, collection)
end
return t
end
---
-- Creates an array of elements split into two groups, the first of
-- which contains elements predicate returns truthy for, while the second
-- of which contains elements predicate returns falsey for. The predicate
-- is bound to selfArg and invoked with three arguments:
-- (value, index|key, collection).
-- @usage _.print(_.partition({1, 2, 3, 4, 5, 6, 7}, function (n)
-- return n > 3
-- end))
-- --> {{4, 5, 6, 7}, {1, 2, 3}}
--
-- @param collection The collection to iterate over. (table|string)
-- @param[opt=_.identity] predicate The function invoked per iteration
-- @param[opt] selfArg The self binding of predicate.
-- @return Returns the array of grouped elements.
_.partition = function (collection, predicate, selfArg)
local t = {{}, {}}
for k, v in _.iter(collection) do
if callIteratee(predicate, selfArg, v, k, collection) then
_.push(t[1], v)
else
_.push(t[2], v)
end
end
return t
end
---
-- Gets the property value of path from all elements in collection.
-- @usage local users = {
-- { user = 'barney', age = 36, child = {age = 5}},
-- { user = 'fred', age = 40, child = {age = 6} }
-- }
-- _.print(_.pluck(users, {'user'}))
-- --> {"barney", "fred"}
-- _.print(_.pluck(users, {'child', 'age'}))
-- --> {5, 6}
--
-- @param collection The collection to iterate over.
-- @param path The path of the property to pluck.
_.pluck = function (collection, path)
local t = {}
for k, value in _.iter(collection) do
_.push(t, _.get(value, path))
end
return t
end
---
-- Reduces collection to a value which is the accumulated result of
-- running each element in collection through iteratee, where each
-- successive invocation is supplied the return value of the previous.
-- If accumulator is not provided the first element of collection is used
-- as the initial value. The iteratee is bound to selfArg and invoked
-- with four arguments: (accumulator, value, index|key, collection).
-- @usage _.print(_.reduce({1, 2, 3}, function(total, n)
-- return n + total;
-- end))
-- --> 6
-- _.print(_.reduce({a = 1, b = 2}, function(result, n, key)
-- result[key] = n * 3
-- return result;
-- end, {}))
-- --> {["a"]=3, ["b"]=6}
--
-- @param collection The collection to iterate over.
-- @param[opt=_.identity] iteratee The function invoked per iteration.
-- @param[opt=<first element>] accumulator The initial value.
-- @param[opt] selfArg The self binding of predicate.
-- @return Returns the accumulated value.
_.reduce = function (collection, iteratee, accumulator, selfArg)
local accumulator = accumulator
for k, v in _.iter(collection) do
if _.isNil(accumulator) then
accumulator = v
else
accumulator = callIteratee(iteratee, selfArg, accumulator, v, k, collection)
end
end
return accumulator
end
---
-- This method is like _.reduce except that it iterates over elements
-- of collection from right to left.
-- @usage local array = {0, 1, 2, 3, 4, 5};
-- _.print(_.reduceRight(array, function(str, other)
-- return str .. other
-- end, ''))
-- --> 543210
--
-- @param collection The collection to iterate over.
-- @param[opt=_.identity] iteratee The function invoked per iteration.
-- @param[opt=<first element>] accumulator The initial value.
-- @param[opt] selfArg The self binding of predicate.
-- @return Returns the accumulated value.
_.reduceRight = function (collection, iteratee, accumulator, selfArg)
local accumulator = accumulator
for k, v in _.iterRight(collection) do
if _.isNil(accumulator) then
accumulator = v
else
accumulator = callIteratee(iteratee, selfArg, accumulator, v, k, collection)
end
end
return accumulator
end
---
-- The opposite of [_.filter](#_.filter); this method returns the elements of
-- collection that predicate does not return truthy for.
-- @usage _.print(_.reject({1, 2, 3, 4, '5', 6, '7'}, _.isNumber))
-- --> {"5", "7"}
--
-- @param collection The collection to iterate over. (table|string)
-- @param[opt=_.identity] predicate The function invoked per iteration
-- @param[opt] selfArg The self binding of predicate.
_.reject = function (collection, predicate, selfArg)
return filter(collection, predicate, selfArg, true)
end
---
-- Gets a random element or n random elements from a collection.
-- @usage _.print(_.sample({1, 2, 3, a=4, b='x', 5, 23, 24}, 4))
-- --> {5, "x", 1, 23}
-- _.print(_.sample({1, 2, 3, a=4, b='x', 5, 23, 24}))
-- --> 4
--
-- @param collection The collection to sample.
-- @param[opt=1] n The number of elements to sample.
-- @return Returns the random sample(s).
_.sample = function (collection, n)
local n = n or 1
local t = {}
local keys = _.keys(collection)
for i=1, n do
local pick = keys[_.random(1, #keys)]
_.push(t, _.get(collection, {pick}))
end
return #t == 1 and t[1] or t
end
---
-- Gets the size of collection by returning its length for array-like
-- values or the number of own enumerable properties for objects.
-- @usage _.print(_.size({'abc', 'def'}))
-- --> 2
-- _.print(_.size('abcdefg'))
-- --> 7
-- _.print(_.size({a=1, b=2,c=3}))
-- --> 3
--
-- @param collection The collection to inspect.
-- @return Returns the size of collection.
_.size = function (collection)
local c = 0
for k, v in _.iter(collection) do
c = c + 1
end
return c
end
---
-- Checks if predicate returns truthy for any element of collection.
-- The function returns as soon as it finds a passing value and does
-- not iterate over the entire collection. The predicate is bound to
-- selfArg and invoked with three arguments: (value, index|key, collection).
--
-- @usage _.print(_.some({1, 2, 3, 4, 5, 6}, _.isString))
-- --> false
-- _.print(_.some({1, 2, 3, 4, '5', 6}, _.isString))
-- --> true
-- @param collection The collection to iterate over. (table|string)
-- @param[opt=_.identity] predicate The function invoked per iteration
-- @param[opt] selfArg The self binding of predicate.
-- @return Returns true if any element passes the predicate check, else false.
_.some = function (collection, predicate, selfArg)
for k, v in _.iter(collection) do
if callIteratee(predicate, selfArg, v, k, collection) then
return true
end
end
return false
end
---
-- Creates an array of elements, sorted in ascending order by the
-- results of running each element in a collection through iteratee.
-- The iteratee is bound to selfArg and
-- invoked with three arguments: (value, index|key, collection).
-- @usage local t = {1, 2, 3}
-- _.print(_.sortBy(t, function (a)
-- return math.sin(a)
-- end))
-- --> {1, 3, 2}
-- local users = {
-- { user='fred' },
-- { user='alex' },
-- { user='zoee' },
-- { user='john' },
-- }
-- _.print(_.sortBy(users, function (a)
-- return a.user
-- end))
-- --> {{["user"]="alex"}, {["user"]="fred"}, {["user"]="john"}, {["user"]="zoee"}}
--
-- @param collection The collection to iterate over.
-- @param[opt=_.identity] predicate The function invoked per iteration
-- @param[opt] selfArg The self binding of predicate.
-- @return Returns the new sorted array.
_.sortBy = function (collection, predicate, selfArg)
local t ={}
local empty = true
local previous
for k, v in _.iter(collection) do
if empty then
_.push(t, v)
previous = callIteratee(predicate, selfArg, v, k, collection)
empty = false
else
local r = callIteratee(predicate, selfArg, v, k, collection)
if _.lt(previous, r) then
table.insert(t, v)
previous = r
else
table.insert(t, #t, v)
end
end
end
return t
end
---
-- Iterates over elements of collection, returning the first element
-- predicate returns truthy for. The predicate is bound to selfArg and
-- invoked with three arguments: (value, index|key, collection).
-- @usage _.print(_.find({{a = 1}, {a = 2}, {a = 3}, {a = 2}, {a = 3}}, function(v)
-- return v.a == 3
-- end))
-- --> {[a]=3}
--
-- @param collection The collection to search. (table|string)
-- @param predicate The function invoked per iteration
-- @param selfArg The self binding of predicate.
_.find = function (collection, predicate, selfArg)
for k, v in _.iter(collection) do
if callIteratee(predicate, selfArg, v, k, collection) then
return v
end
end
end
---
-- This method is like _.find except that it iterates over elements of
-- collection from right to left.
-- @usage _.findLast({{a = 1}, {a = 2}, {a = 3, x = 1}, {a = 2}, {a = 3, x = 2}},
-- function(v)
-- return v.a == 3
-- end))
-- --> {[a]=3, [x]=2}
--
-- @param collection The collection to search. (table|string)
-- @param predicate The function invoked per iteration
-- @param selfArg The self binding of predicate.
_.findLast = function (collection, predicate, selfArg)
for k, v in _.iterRight(collection) do
if callIteratee(predicate, selfArg, v, k, collection) then
return v
end
end
end
--- Function
-- @section Function
---
-- This method creates a function that invokes func once it’s called n
-- or more times.
-- @usage local printAfter3 = _.after(3, print)
-- for i = 1, 5 do
-- printAfter3('done', i)
-- end
-- --> done 4
-- --> done 5
--
-- @param n The number of calls before func invoked.
-- @param func The function to restrict.
-- @return Returns the new restricted function.
_.after = function(n, func)
local i = 1
return function(...)
if _.gt(i, n) then
return func(...)
end
i = i + 1
end
end
---
-- Creates a function that accepts up to n arguments ignoring any
-- additional arguments.
-- @usage local printOnly3 =_.ary(print, 3)
-- printOnly3(1, 2, 3, 'x', 'y', 6)
-- --> 1 2 3
--
-- @param func The function to cap arguments for.
-- @param n the arity cap.
-- @return Returns the new function
_.ary = function(func, n)
return function(...)
if n == 1 then
return func((...))
else
local t = _.table(...)
local first = _.take(t, n)
return func(_.args(first))
end
end
end
---
-- Creates a function that invokes func while it’s called less than n times.
-- Subsequent calls to the created function return the result of the
-- last func invocation.
-- @usage local printBefore3 = _.before(3, print)
-- for i = 1, 10 do
-- printBefore3(i, 'ok')
-- end
-- --> 1 ok
-- --> 2 ok
-- --> 3 ok
--
-- @param n The number of calls at which func is no longer invoked.
-- @param func The function to restrict.
-- @return Returns the new restriced function.
_.before = function (n, func)
local i = 1
local result
return function (...)
if _.lte(i, n) then
result = func(...)
end
i = i + 1
return result
end
end
---
-- Creates a function that runs each argument through a corresponding
-- transform function.
-- @usage local increment = function(...)
-- return _.args(_.map(_.table(...), function(n)
-- return n + 1
-- end))
-- end
-- local pow = function(...)
-- return _.args(_.map(_.table(...), function(n)
-- return n * n
-- end))
-- end
-- local modded = _.modArgs(function(...)
-- print(...)
-- end, {increment, increment}, pow)
-- modded(0, 1, 2)
-- --> 4 9 16
--
-- @param func The function to wrap
-- @param ... The functions to transform arguments, specified as
-- individual functions or arrays of functions.
-- @return Returns the new function.
_.modArgs = function (func, ...)
local transforms = {}
for i, v in ipairs( _.table(...)) do
if _.isFunction(v) then
_.push(transforms, v)
elseif _.isTable(v) then
for k2, v2 in _.iter(v) do
if _.isFunction(v2) then _.push(transforms, v2) end
end
end
end
return function(...)
local args
for i, transform in ipairs(transforms) do
if _.isNil(args) then
args = _.table(transform(...))
else
args = _.table(transform(_.args(args)))
end
end
if _.isNil(args) then
return func(...)
else
return func(_.args(args))
end
end
end
---
-- Creates a function that negates the result of the predicate func.
-- The func predicate is invoked with arguments of the created function.
-- @usage local isEven = function (n)
-- return n % 2 == 0
-- end
-- local isOdd = _.negate(isEven)
-- _.print(_.filter({1, 2, 3, 4, 5, 6}, isEven))
-- --> {2, 4, 6}
-- _.print(_.filter({1, 2, 3, 4, 5, 6}, isOdd))
-- --> {1, 3, 5}
--
-- @param func The preadicate to negate.
-- @return Returns the new function
_.negate = function (func)
return function(...)
return not func(...)
end
end
---
-- Creates a function that is restricted to invoking func once. Repeat
-- calls to the function return the value of the first call. The func
-- is invoked with arguments of the created function.
-- @usage local createApp = function(version)
-- print('App created with version '..version)
-- return version
-- end
-- local initialize = _.once(createApp)
-- initialize(1.1)
-- initialize(1.1)
-- initialize(1.1)
-- --> App created with version 1.1
-- --> 1.1
-- --> 1.1
-- --> 1.1
--
-- @param func The function to restrict.
-- @return Returns the new function.
_.once = function (func)
local called = false;
local result
return function(...)
if not called then
result = func(...)
called = true
end
return result
end
end
---
-- Creates a function that invokes func with arguments arranged according
-- to the specified indexes where the argument value at the first index
-- is provided as the first argument, the argument value at the second
-- index is provided as the second argument, and so on.
-- @usage local rearged = _.rearg(function(a, b, c)
-- return {a, b, c};
-- end, 2, 1, 3)
-- _.print(rearged('a', 'b', 'c'))
-- --> {"b", "a", "c"}
-- _.print(rearged('b', 'a', 'c'))
-- --> {"a", "b", "c"}
--
-- @param func The function to rearrange arguments for.
-- @param ... The arranged argument indexes, specified as individual
-- indexes or arrays of indexes.
-- @return Returns the new function.
_.rearg = function (func, ...)
local indexes = {}
for i, v in ipairs(_.table(...)) do
if _.isNumber(v) then
_.push(indexes, v)
elseif _.isTable(v) then
for k2, v2 in _.iter(v) do
if _.isNumber(v2) then _.push(indexes, v2) end
end
end
end
return function(...)
local args = _.table(...)
local newArgs = {}
for i, index in ipairs(indexes) do
_.push(newArgs, args[index])
end
if #indexes == 0 then
return func(...)
else
return func(_.args(newArgs))
end
end
end
--- Lang
-- @section Lang
---
---
-- Cast value to arguments
-- @usage print(_.args({1, 2, 3}))
-- --> 1 2 3
--
-- @param value value to cast
-- @return Returns arguments
_.args = function (value)
if _.isTable(value) then return table.unpack(value)
else return table.unpack({value})
end
end
---
-- Checks if value is greater than other.
-- @usage _.print(_.gt(1, 3))
-- --> false
-- _.print(_.gt(4, 3))
-- --> true
--
-- @param value The value to compare.
-- @param other The other value to compare.
_.gt = function (value, other, ...)
local value, other = _.cast(value, other)
if _.isString(value) or _.isNumber(value) then
return value > other
elseif _.isFunction(value) then
return value(...) > other(...)
end
return false
end
---
-- Checks if value is greater than other.
-- @usage _.print(_.gte(1, 3))
-- --> false
-- _.print(_.gte(3, 3))
-- --> true
--
-- @param value The value to compare.
-- @param other The other value to compare.
_.gte = function (value, other, ...)
if _.isNil(value) or _.isBoolean(value) then
return value == other
end
local value, other = _.cast(value, other)
if _.isString(value) or _.isNumber(value) then
return value >= other
elseif _.isFunction(value) then
return value(...) >= other(...)
elseif _.isTable(value) then
return false
end
return false
end
---
-- Checks if value is classified as a boolean primitive.
-- @usage _.print(_.isBoolean(false))
-- --> true
-- _.print(_.isBoolean('x'))
-- --> false
--
-- @param value the value to check
-- @return Returns true if value is correctly classified, else false.
_.isBoolean = function(value)
return type(value) == 'boolean'
end
---
-- Checks if value is empty. A value is considered empty unless it’s an
-- arguments table, array, string with a length greater than 0 or an
--object with own enumerable properties.
--@usage _.print(_.isEmpty(true))
-- --> true
-- _.print(_.isEmpty(1))
-- --> true
-- _.print(_.isEmpty({1, 2, 3}))
-- --> false
-- _.print(_.isEmpty({a= 1}))
-- --> false
--
-- @param value The value to inspect.
-- @return Returns true if value is empty, else false.
_.isEmpty = function (value)
if _.isString(value) then
return #value == 0
elseif _.isTable(value) then
local i = 0
for k, v in _.iter(value) do
i = i + 1
end
return i == 0
else
return true
end
end
---
-- Checks if value is classified as a function primitive.
-- @usage _.print(_.isFunction(function() end))
-- --> true
-- _.print(_.isFunction(1))
-- --> false
--
-- @param value the value to check
-- @return Returns true if value is correctly classified, else false.
_.isFunction = function(value)
return type(value) == 'function'
end
---
-- Checks if value is classified as a nil primitive.
-- @usage _.print(_.isNil(variable)
-- --> true
-- variable = 1
-- _.print(_.isNil(variable))
-- --> false
--
-- @param value the value to check
-- @return Returns true if value is correctly classified, else false.
_.isNil = function(value)
return type(value) == 'nil'
end
---
-- Checks if value is classified as a number primitive.
-- @usage _.print(_.isNumber(1))
-- --> true
-- _.print(_.isNumber('1'))
-- --> false
--
-- @param value the value to check
-- @return Returns true if value is correctly classified, else false.
_.isNumber = function(value)
return type(value) == 'number'
end
---
-- Checks if value is classified as a string primitive.
-- @usage _.print(_.isString('1'))
-- --> true
-- _.print(_.isString(1))
-- --> false
--
-- @param value the value to check
-- @return Returns true if value is correctly classified, else false.
_.isString = function(value)
return type(value) == 'string'
end
---
-- Checks if value is classified as a table primitive.
-- @usage _.print(_.isTable({'1'}))
-- --> true
-- _.print(_.isString(1))
-- --> false
--
-- @param value the value to check
-- @return Returns true if value is correctly classified, else false.
_.isTable = function(value)
return type(value) == 'table'
end
-- local implicitCast function (...)
-- if
-- end
---
-- Checks if value is less than other.
-- @usage _.print(_.lt(1, 3))
-- --> true
-- _.print(_.lt(3, 3))
-- --> false
--
-- @param value The value to compare.
-- @param other The other value to compare.
_.lt = function (value, other, ...)
local value, other = _.cast(value, other)
if _.isString(value) or _.isNumber(value) then
return value < other
elseif _.isFunction(value) then
return value(...) < other(...)
end
return false
end
---
-- Checks if value is less than or euqal to other.
-- @usage _.print(_.lt(4, 3))
-- --> false
-- _.print(_.lt(3, 3))
-- --> true
-- @param value The value to compare.
-- @param other The other value to compare.
_.lte = function (value, other, ...)
if _.isNil(value) or _.isBoolean(value) then
return value == other
end
local value, other = _.cast(value, other)
if _.isString(value) or _.isNumber(value) then
return value <= other
elseif _.isFunction(value) then
return value(...) <= other(...)
elseif _.isTable(value) then
return false
end
return false
end
_.cast = function (a, b)
if type(a) == type(b) then return a, b end
local cast
if _.isString(a) then cast = _.str
elseif _.isBoolean(a) then cast = _.bool
elseif _.isNumber(a) then cast = _.num
elseif _.isFunction(a) then cast = _.func
elseif _.isTable(a) then cast = _.table
end
return a, cast(b)
end
---
-- Cast parameters to a function that return passed parameters.
-- @usage local f = _.func(1, 2, 3)
-- _.print(f())
-- --> 1 2 3
--
-- @param value value to cast
-- @param ... The parameters to pass to any detected function
-- @return casted value
_.func = function (...)
local t = _.table(...)
return function ()
return _.args(t)
end
end
---
-- Cast parameters to table using table.pack
-- @usage print(_.table(1, 2, 3))
-- --> {1, 2, 3}
-- print(_.table("123"))
-- --> {"123"}
-- print(_.table(0))
-- --> {0}
--
-- @param value value to cast
-- @param ... The parameters to pass to any detected function
-- @return casted value
_.table = function (...)
return table.pack(...)
end
---
-- Cast anything to boolean. If any function detected, call and cast its
-- result. Return false for 0, nil, table and empty string.
-- @usage print(_.bool({1, 2, 3}))
-- --> false
-- print(_.bool("123"))
-- --> true
-- print(_.bool(0))
-- --> false
-- print(_.bool(function(a) return a end, "555"))
-- --> true
--
-- @param value value to cast
-- @param ... The parameters to pass to any detected function
-- @return casted value
_.bool = function (value, ...)
local bool = false
if _.isString(value) then
bool = #value > 0
elseif _.isBoolean(value) then
bool = value
elseif _.isNumber(value) then
bool = value ~= 0
elseif _.isFunction(value) then
bool = _.bool(value(...))
end
return bool
end
---
-- Cast anything to number. If any function detected, call and cast its
-- result. Return 0 for nil and table.
-- @usage print(_.num({1, 2, 3}))
-- --> 0
-- print(_.num("123"))
-- --> 123
-- print(_.num(true))
-- --> 1
-- print(_.num(function(a) return a end, "555"))
-- --> 555
--
-- @param value value to cast
-- @param ... The parameters to pass to any detected function
-- @return casted value
_.num = function (value, ...)
local num = 0
if _.isString(value) then
ok = pcall(function()
num = value + 0
end)
if not ok then
num = math.huge
end
elseif _.isBoolean(value) then
num = value and 1 or 0
elseif _.isNumber(value) then
num = value
elseif _.isFunction(value) then
num = _.num(value(...))
end
return num
end
local dblQuote = function (v)
return '"'..v..'"'
end
---
-- Cast anything to string. If any function detected, call and cast its
-- result.
-- @usage print(_.str({1, 2, 3, 4, {k=2, {'x', 'y'}}}))
-- --> {1, 2, 3, 4, {{"x", "y"}, ["k"]=2}}
-- print(_.str({1, 2, 3, 4, function(a) return a end}, 5))
-- --> {1, 2, 3, 4, 5}
--
-- @param value value to cast
-- @param ... The parameters to pass to any detected function
-- @return casted value
_.str = function (value, ...)
local str = '';
-- local v;
if _.isString(value) then
str = value
elseif _.isBoolean(value) then
str = value and 'true' or 'false'
elseif _.isNil(value) then
str = 'nil'
elseif _.isNumber(value) then
str = value .. ''
elseif _.isFunction(value) then
str = _.str(value(...))
elseif _.isTable(value) then
str = '{'
for k, v in pairs(value) do
v = _.isString(v) and dblQuote(v) or _.str(v, ...)
if _.isNumber(k) then
str = str .. v .. ', '
else
str = str .. '[' .. dblQuote(k) .. ']=' .. v .. ', '
end
end
str = str:sub(0, #str - 2) .. '}'
end
return str
end
--- Number
-- @section Number
---
-- Checks if n is between start and up to but not including, end.
-- If end is not specified it’s set to start with start then set to 0.
-- @usage print(_.inRange(-3, -4, 8))
-- --> true
--
-- @param n The number to check.
-- @param start The start of the range.
-- @param stop The end of the range.
-- @return Returns true if n is in the range, else false.
_.inRange = function (n, start, stop)
local _start = _.isNil(stop) and 0 or start or 0
local _stop = _.isNil(stop) and start or stop or 1
return n >= _start and n < _stop
end
---
-- Produces a random number between min and max (inclusive).
-- If only one argument is provided a number between 0 and the given
-- number is returned. If floating is true, a floating-point number is
-- returned instead of an integer.
-- @usage _.print(_.random())
-- --> 1
-- _.print(_.random(5))
-- --> 3
-- _.print(_.random(5, 10, true))
-- --> 8.8120200577248
--
-- @param[opt=0] min the minimum possible value.
-- @param[opt=1] max the maximum possible value.
-- @param[opt=false] floating Specify returning a floating-point number.
-- @return Returns the random number.
_.random = function (min, max, floating)
local minim = _.isNil(max) and 0 or min or 0
local maxim = _.isNil(max) and min or max or 1
math.randomseed(os.clock() * math.random(os.time()))
local r = math.random(minim, maxim)
if floating then
r = r + math.random()
end
return r
end
--- Object
-- @section Object
---
-- Assigns own enumerable string keyed properties of source objects
-- to the destination object. Source objects are applied from left
-- to right. Subsequent sources overwrite property assignments of
-- previous sources.
--
-- @usage _.print(_.assign({ a = 0 }, { a = 1 }, { b = 3 }))
-- --> { a = 1, b = 3 }
--
-- @param object The destination object
-- @param ... The source objects
-- @return Returns object
_.assign = function(object, ...)
for index = 1, select('#', ...) do
for k, v in pairs(select(index, ...)) do
object[k] = v
end
end
return object
end
---
-- Gets the property value at path of object. If the resolved value
-- is nil the defaultValue is used in its place.
-- @usage local object = {a={b={c={d=5}}}}
-- _.print(_.get(object, {'a', 'b', 'c', 'd'}))
-- --> 5
--
-- @param object The object to query.
-- @param path The path of the property to get.
-- @param[opt=nil] defaultValue The value returned if the resolved value is nil.
-- @return Returns the resolved value.
_.get = function (object, path, defaultValue)
if _.isTable(object) then
local value = object
local c = 1
while not _.isNil(path[c]) do
if not _.isTable(value) then return defaultValue end
value = value[path[c]]
c = c + 1
end
return value or defaultValue
elseif _.isString(object) then
local index = path[1]
return object:sub(index, index)
end
end
---
-- Checks if path is a direct property.
-- @usage local object = {a={b={c={d}}}}
-- print(_.has(object, {'a', 'b', 'c'}))
-- --> true
--
-- @param object The object to query
-- @param path The path to check (Array)
_.has = function (object, path)
local obj = object
local c = 1
local exist = true
while not _.isNil(path[c]) do
obj = obj[path[c]]
if _.isNil(obj) then
exist = false
break
end
c = c + 1
end
return exist
end
---
-- This method is like _.find except that it returns the key of the
-- first element predicate returns truthy for instead of the element itself.
-- @usage _.print(_.findKey({a={a = 1}, b={a = 2}, c={a = 3, x = 1}},
-- function(v)
-- return v.a == 3
-- end))
-- --> c
--
-- @param object The collection to search. (table|string)
-- @param predicate The function invoked per iteration
-- @param selfArg The self binding of predicate.
-- @return Returns the key of the matched element, else nil
_.findKey = function (object, predicate, selfArg)
for k, v in _.iter(object) do
if callIteratee(predicate, selfArg, v, k, object) then
return k
end
end
end
---
-- This method is like _.find except that it returns the key of the
-- first element predicate returns truthy for instead of the element itself.
-- @usage _.print(_.findLastKey({a={a=3}, b={a = 2}, c={a=3, x = 1}},
-- function(v)
-- return v.a == 3
-- end))
-- --> c
--
-- @param object The object to search. (table|string)
-- @param predicate The function invoked per iteration
-- @param selfArg The self binding of predicate.
-- @return Returns the key of the matched element, else nil
_.findLastKey = function (object, predicate, selfArg)
for k, v in _.iterRight(object) do
if callIteratee(predicate, selfArg, v, k, object) then
return k
end
end
end
---
-- Creates an array of function property names from all enumerable
-- properties, own and inherited, of object.
-- @usage _.print(_.functions(table))
-- --> {"concat", "insert", "maxn", "pack", "remove", "sort", "unpack"}
--
-- @param object The object to inspect.
-- @return Returns the new array of property names.
_.functions = function(object)
local t = {}
for k, v in _.iter(object) do
if _.isFunction(v) then
_.push(t, k)
end
end
return t
end
---
-- Creates an object composed of the inverted keys and values of object.
-- If object contains duplicate values, subsequent values overwrite
-- property assignments of previous values unless multiValue is true.
-- @usage _.print(_.invert({a='1', b='2', c='3', d='3'}))
-- --> {[2]="b", [3]="d", [1]="a"}
-- _.print(_.invert({a='1', b='2', c='3', d='3'}, true))
-- --> {[2]="b", [3]={"c", "d"}, [1]="a"}
--
-- @param object The object to invert.
-- @param multiValue Allow multiple values per key.
-- @return Returns the new inverted object.
_.invert = function (object, multiValue)
local t = {}
for k, v in _.iter(object) do
if multiValue and not _.isNil(t[v]) then
t[v] = { t[v] }
_.push(t[v], k)
else
t[v] = k
end
end
return t
end
local getSortedKeys = function(collection, desc)
local sortedKeys = {}
for k, v in pairs(collection) do
table.insert(sortedKeys, k)
end
if desc then
table.sort(sortedKeys, _.gt)
else
table.sort(sortedKeys, _.lt)
end
return sortedKeys
end
---
-- Creates an array of the own enumerable property names of object.
-- @usage _.print(_.keys("test"))
-- --> {1, 2, 3, 4}
-- _.print(_.keys({a=1, b=2, c=3}))
-- --> {"c", "b", "a"}
--
-- @param object The object to query. (table|string)
-- @return Returns the array of property names.
_.keys = function (object)
if _.isTable(object) then
return getSortedKeys(object)
elseif _.isString(object) then
local keys = {}
for i=1, #object do
keys[i] = i
end
return keys
end
end
---
-- Creates a two dimensional array of the key-value pairs for object.
-- @usage _.print(_.pairs({1, 2, 'x', a='b'}))
-- --> {{1, 1}, {2, 2}, {3, "x"}, {"a", "b"}}
--
-- @param object The object to query
-- @return Returns the new array of key-value pairs.
_.pairs = function (object)
local t = {}
for k, v in _.iter(object) do
_.push(t, {k, v})
end
return t
end
---
-- This method is like _.get except that if the resolved value is a
-- function it’s invoked with additional parameters and its result is returned.
-- @usage local object = {a=5, b={c=function(a) print(a) end}}
-- _.result(object, {'b', 'c'}, nil, 5)
-- --> 5
--
-- @param object The object to query.
-- @param path The path of the property to get.
-- @param[opt=nil] defaultValue The value returned if the resolved value is nil.
-- @param ... Additional parameters to pass to function
-- @return Returns the resolved value.
_.result = function (object, path, defaultValue, ...)
local result = _.get(object, path, defaultValue)
if _.isFunction(result) then
return result(...)
else
return result
end
end
---
-- Creates an array of the own enumerable property values of object.
-- @usage _.print(_.values("test"))
-- --> {"t", "e", "s", "t"}
-- _.print(_.values({a=1, b=2, c=3}))
-- --> {1, 3, 2}
--
-- @param object The object to query. (table|string)
-- @return Returns the array of property values.
_.values = function (object)
local t = {}
for k, v in _.iter(object) do
_.push(t, v)
end
return t
end
--- String
-- @section String
--- Utility
-- @section Utility
---
-- Creates a function that returns value.
-- @usage local object = {x=5}
-- local getter = _.constant(object)
-- _.print(getter() == object);
-- --> true
--
-- @param value Any value.
-- @return Returns the new function.
_.constant = function(value)
return _.func(value)
end
---
-- This method returns the first argument provided to it.
-- @usage local object = {x=5}
-- _.print(_.identity(object) == object);
-- --> true
--
-- @param value Any value.
-- @return Returns value.
_.identity = function(...) return ... end
local iterCollection = function(table, desc)
local sortedKeys = getSortedKeys(table, desc)
local i = 0
return function ()
if _.lt(i, #sortedKeys) then
i = i + 1
local key = sortedKeys[i]
return key, table[key]
end
end
end
_.iter = function(value)
if _.isString(value) then
local i = 0
return function()
if _.lt(i, #value) then
i = i + 1
local c = value:sub(i, i)
return i, c
end
end
elseif _.isTable(value) then
return iterCollection(value)
else
return function() end
end
end
_.iterRight = function(value)
if _.isString(value) then
local i = #value + 1
return function()
if _.gt(i, 1) then
i = i - 1
local c = value:sub(i, i)
return i, c
end
end
elseif _.isTable(value) then
return iterCollection(value, true)
else
return function() end
end
end
---
-- A no-operation function that returns nil regardless of the arguments
-- it receives.
-- @usage local object = {x=5}
-- _.print(_.noop(object) == nil);
-- --> true
--
-- @param ... Any arguments
-- @return Returns nil
_.noop = function(...) return nil end
---
-- Print more readable representation of arguments using _.str
-- @usage _.print({1, 2, 3, 4, {k=2, {'x', 'y'}}})
-- --> {1, 2, 3, 4, {{"x", "y"}, [k]=2}}
--
-- @param ... values to print
-- @return Return human readable string of the value
_.print = function(...)
local t = _.table(...)
for i, v in ipairs(t) do
t[i] = _.str(t[i])
end
return print(_.args(t))
end
---
-- Creates an array of numbers (positive and/or negative) progressing
-- from start up to, including, end.
-- If end is not specified it’s set to start with start then set to 1.
-- @usage _.print(_.range(5, 20, 3))
-- --> {5, 8, 11, 14, 17, 20}
--
-- @param[opt=1] start The start of the range.
-- @param stop Then end of the range.
-- @param[opt=1] step The value to increment or decrement by
-- @return Returns the new array of numbers
_.range = function(start, ...)
local start = start
local args = _.table(...)
local a, b, c
if #args == 0 then
a = 1 -- according to lua
b = start
c = 1
else
a = start
b = args[1]
c = args[2] or 1
end
local t = {}
for i = a, b, c do
_.push(t, i)
end
return t
end
return _
Duel.LoadScript("lodash.lua")
-- not finished
function Group.Levels(g)
local levels = {}
for c in aux.Next(g) do
table.insert(levels, c:GetLevel())
end
table.sort(levels)
return levels
end
function Group.IsFlush(g)
return g:GetClassCount(Card.IsAttribute) == 1
end
function Group.IsStraight(g)
local levels = g:Levels()
for i = 1, #levels - 1 do
if levels[i + 1] ~= levels[i] + 1 then
return false
end
end
end
function Group.HighCardValue(g) -- 20 bits
local levels = {}
for c in aux.Next(g) do
table.insert(levels, c:GetLevel())
end
table.sort(levels)
return levels[1] + (levels[2] << 4) + (levels[3] << 8) + (levels[4] << 12) + (levels[5] << 16)
end
function Group.FindSameLevel(g, count)
end
local cardTypes = {
{
name = "straight flush",
level = 9,
condition = function(g)
return isFlush(g) and isStraight(g)
end,
value = Group.HighCardValue,
},
{
name = "4 of a kind",
level = 8,
condition = function(g)
return g:CheckSubGroup(g, function(sg) return sg:GetClassCount(Card.GetLevel) == 1 end, 4, 4)
end,
value = function(g)
local uniqueCard = g:SearchCard(function(c)
return not g:IsExists(function(c2)
return c:GetLevel() == c2:GetLevel()
end, c)
end)
local g2=g-c
return (g2:GetFirst():GetLevel() << 4) + uniqueCard:GetLevel()
end,
},
{
name = "full house",
level = 7,
condition = function(g)
return g:CheckSubGroup(g, function(sg) return sg:GetClassCount(Card.GetLevel) == 1 and (sg-g):GetClassCount(Card.GetLevel) == 1 end, 3, 3) and
end,
value = function(g)
local uniqueCard = g:SearchCard(function(c)
return not g:IsExists(function(c2)
return c:GetLevel() == c2:GetLevel()
end, c)
end)
local g2=g-c
return (g2:GetFirst():GetLevel() << 4) + uniqueCard:GetLevel()
end,
},
{
name = "flush",
level = 6,
condition = function(g)
return isFlush(g)
end,
value = Group.HighCardValue,
},
{
name = "straight",
level = 5,
condition = function(g)
return isStraight(g)
end,
value = Group.HighCardValue,
},
{
name = "3 of a kind",
level = 4,
condition = function(g)
return g:CheckSubGroup(g, function(sg) return sg:GetClassCount(Card.GetLevel) == 1 end, 3, 3)
end,
value = function(g)
local uniqueCard = g:SearchCard(function(c)
return not g:IsExists(function(c2)
return c:GetLevel() == c2:GetLevel()
end, c)
end)
local g2=g-c
return (g2:GetFirst():GetLevel() << 4) + uniqueCard:GetLevel()
end,
},
{
name = "2 pair",
level = 3,
condition = function(g)
return g:CheckSubGroup(g, function(sg) return sg:GetClassCount(Card.GetLevel) == 1 end, 2, 2) and
g:CheckSubGroup(g, function(sg) return sg:GetClassCount(Card.GetLevel) == 1 end, 2, 2)
end,
}
}
local function grantDecktop(e)
local e3=Effect.GlobalEffect()
e3:SetType(EFFECT_TYPE_FIELD+EFFECT_TYPE_GRANT)
e3:SetProperty(EFFECT_FLAG_IGNORE_IMMUNE+EFFECT_FLAG_SET_AVAILABLE)
e3:SetTargetRange(LOCATION_DECK,LOCATION_DECK)
e3:SetTarget(function(e,c)
local tp=c:GetControler()
local dg=Duel.GetFieldGroup(tp,LOCATION_DECK,0)
local g=dg:GetMinGroup(Card.GetSequence)
return g:GetFirst()==c
end)
e3:SetLabelObject(e)
Duel.RegisterEffect(e3,0)
end
local function gf(c,tp)
return (c:IsFaceup() or c:IsControler(tp)) and c:IsAbleToGrave()
end
local function sf(c,g)
return g:IsExists(Card.IsCode,2,c,c:GetCode())
end
function Auxiliary.PreloadUds()
local e1=Effect.GlobalEffect()
e1:SetType(EFFECT_TYPE_FIELD+EFFECT_TYPE_CONTINUOUS)
e1:SetCode(EVENT_FREE_CHAIN)
e1:SetProperty(EFFECT_FLAG_SET_AVAILABLE)
e1:SetRange(LOCATION_DECK)
e1:SetCondition(function(e,tp,eg,ep,ev,re,r,rp)
local ph=Duel.GetCurrentPhase()
if not (Duel.GetTurnPlayer()==tp and (ph==PHASE_MAIN1 or ph==PHASE_MAIN2) and Duel.GetCurrentChain()==0) then return false end
local g=Duel.GetMatchingGroup(gf,tp,LOCATION_DECK+LOCATION_HAND+LOCATION_ONFIELD+LOCATION_EXTRA,LOCATION_ONFIELD,nil,tp)
return g:IsExists(sf,1,nil,g)
end)
e1:SetOperation(function(e,tp,eg,ep,ev,re,r,rp)
local g=Duel.GetMatchingGroup(gf,tp,LOCATION_DECK+LOCATION_HAND+LOCATION_ONFIELD+LOCATION_EXTRA,LOCATION_ONFIELD,nil,tp)
Duel.Hint(HINT_SELECTMSG,tp,HINTMSG_TOGRAVE)
local tc=g:FilterSelect(tp,sf,1,1,nil,g):GetFirst()
local g2=g:FilterSelect(tp,Card.IsCode,2,2,tc,tc:GetCode())
Duel.Hint(HINT_CARD,0,73915052)
local tg=g2+tc
local codes={}
for tc in aux.Next(tg) do
if tc:IsType(TYPE_MONSTER) then
table.insert(codes,tc:GetCode())
end
end
if Duel.SendtoGrave(tg,REASON_RULE)>0 then
local og=Duel.GetOperatedGroup():Filter(Card.IsLocation,nil,LOCATION_GRAVE)
for oc in aux.Next(og) do
local e1=Effect.CreateEffect(oc)
e1:SetType(EFFECT_TYPE_SINGLE)
e1:SetCode(EFFECT_CANNOT_TRIGGER)
e1:SetProperty(EFFECT_FLAG_CANNOT_DISABLE+EFFECT_FLAG_CANNOT_NEGATE)
e1:SetReset(RESET_EVENT+RESETS_STANDARD+RESET_PHASE+PHASE_END)
oc:RegisterEffect(e1,true)
end
if #codes>0 then
local e2=Effect.CreateEffect(oc)
e2:SetType(EFFECT_TYPE_FIELD)
e2:SetCode(EFFECT_CANNOT_SPECIAL_SUMMON)
e2:SetProperty(EFFECT_FLAG_PLAYER_TARGET+EFFECT_FLAG_CANNOT_DISABLE+EFFECT_FLAG_CANNOT_NEGATE)
e2:SetReset(RESET_PHASE+PHASE_END)
e2:SetTargetRange(1,1)
e2:SetTarget(function(e,c)
return c:IsCode(table.unpack(codes))
end)
Duel.RegisterEffect(e2,tp)
end
Duel.BreakEffect()
Duel.Draw(tp,1,REASON_RULE)
end
end)
e1:SetCountLimit(1,10001)
grantDecktop(e1)
end
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment