no more js
This commit is contained in:
298
internal/array.cm
Normal file
298
internal/array.cm
Normal file
@@ -0,0 +1,298 @@
|
||||
/* array.cm - array creation and manipulation utilities */
|
||||
|
||||
var _isArray = Array.isArray
|
||||
var _slice = Array.prototype.slice
|
||||
var _push = Array.prototype.push
|
||||
var _sort = Array.prototype.sort
|
||||
var _keys = Object.keys
|
||||
|
||||
function array(arg, arg2, arg3, arg4) {
|
||||
// array(number) - create array of size with nulls
|
||||
// array(number, initial_value) - create array with initial values
|
||||
if (typeof arg == 'number') {
|
||||
if (arg < 0) return null
|
||||
var len = number.floor(arg)
|
||||
var result = []
|
||||
|
||||
if (arg2 == null) {
|
||||
for (var i = 0; i < len; i++) result[i] = null
|
||||
} else if (typeof arg2 == 'function') {
|
||||
var arity = arg2.length
|
||||
for (var i = 0; i < len; i++) {
|
||||
result[i] = arity >= 1 ? arg2(i) : arg2()
|
||||
}
|
||||
} else {
|
||||
for (var i = 0; i < len; i++) result[i] = arg2
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
// array(array) - copy
|
||||
// array(array, function, reverse, exit) - map
|
||||
// array(array, another_array) - concat
|
||||
// array(array, from, to) - slice
|
||||
if (_isArray(arg)) {
|
||||
if (arg2 == null) {
|
||||
// Copy
|
||||
return _slice.call(arg)
|
||||
}
|
||||
|
||||
if (typeof arg2 == 'function') {
|
||||
// Map
|
||||
var fn = arg2
|
||||
var reverse = arg3 == true
|
||||
var exit = arg4
|
||||
var result = []
|
||||
|
||||
if (reverse) {
|
||||
for (var i = arg.length - 1; i >= 0; i--) {
|
||||
var val = fn(arg[i], i)
|
||||
if (exit != null && val == exit) break
|
||||
result[i] = val
|
||||
}
|
||||
} else {
|
||||
for (var i = 0; i < arg.length; i++) {
|
||||
var val = fn(arg[i], i)
|
||||
if (exit != null && val == exit) break
|
||||
_push.call(result, val)
|
||||
}
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
if (_isArray(arg2)) {
|
||||
// Concat
|
||||
var result = _slice.call(arg)
|
||||
for (var i = 0; i < arg2.length; i++) {
|
||||
_push.call(result, arg2[i])
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
if (typeof arg2 == 'number') {
|
||||
// Slice
|
||||
var from = arg2
|
||||
var to = arg3
|
||||
var len = arg.length
|
||||
|
||||
if (from < 0) from += len
|
||||
if (to == null) to = len
|
||||
if (to < 0) to += len
|
||||
|
||||
if (from < 0 || from > to || to > len) return null
|
||||
|
||||
return _slice.call(arg, from, to)
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
// array(object) - keys
|
||||
if (typeof arg == 'object' && arg != null && !_isArray(arg)) {
|
||||
return _keys(arg)
|
||||
}
|
||||
|
||||
// array(text) - split into grapheme clusters
|
||||
// array(text, separator) - split by separator
|
||||
// array(text, length) - dice into chunks
|
||||
if (typeof arg == 'string') {
|
||||
if (arg2 == null) {
|
||||
// Split into grapheme clusters (simplified: split into characters)
|
||||
var result = []
|
||||
for (var i = 0; i < arg.length; i++) {
|
||||
_push.call(result, arg[i])
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
if (typeof arg2 == 'string') {
|
||||
// Split by separator
|
||||
return arg.split(arg2)
|
||||
}
|
||||
|
||||
if (typeof arg2 == 'number') {
|
||||
// Dice into chunks
|
||||
var len = number.floor(arg2)
|
||||
if (len <= 0) return null
|
||||
var result = []
|
||||
for (var i = 0; i < arg.length; i += len) {
|
||||
_push.call(result, arg.substring(i, i + len))
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
array.reduce = function(arr, fn, initial, reverse) {
|
||||
if (!_isArray(arr)) return null
|
||||
if (typeof fn != 'function') return null
|
||||
|
||||
var len = arr.length
|
||||
|
||||
if (initial == null) {
|
||||
if (len == 0) return null
|
||||
if (len == 1) return arr[0]
|
||||
|
||||
if (reverse == true) {
|
||||
var acc = arr[len - 1]
|
||||
for (var i = len - 2; i >= 0; i--) {
|
||||
acc = fn(acc, arr[i])
|
||||
}
|
||||
return acc
|
||||
} else {
|
||||
var acc = arr[0]
|
||||
for (var i = 1; i < len; i++) {
|
||||
acc = fn(acc, arr[i])
|
||||
}
|
||||
return acc
|
||||
}
|
||||
} else {
|
||||
if (len == 0) return initial
|
||||
|
||||
if (reverse == true) {
|
||||
var acc = initial
|
||||
for (var i = len - 1; i >= 0; i--) {
|
||||
acc = fn(acc, arr[i])
|
||||
}
|
||||
return acc
|
||||
} else {
|
||||
var acc = initial
|
||||
for (var i = 0; i < len; i++) {
|
||||
acc = fn(acc, arr[i])
|
||||
}
|
||||
return acc
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
array.for = function(arr, fn, reverse, exit) {
|
||||
if (!_isArray(arr)) return null
|
||||
if (typeof fn != 'function') return null
|
||||
|
||||
if (reverse == true) {
|
||||
for (var i = arr.length - 1; i >= 0; i--) {
|
||||
var result = fn(arr[i], i)
|
||||
if (exit != null && result == exit) return exit
|
||||
}
|
||||
} else {
|
||||
for (var i = 0; i < arr.length; i++) {
|
||||
var result = fn(arr[i], i)
|
||||
if (exit != null && result == exit) return exit
|
||||
}
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
array.find = function(arr, fn, reverse, from) {
|
||||
if (!_isArray(arr)) return null
|
||||
|
||||
var len = arr.length
|
||||
|
||||
if (typeof fn != 'function') {
|
||||
// Compare exactly
|
||||
var target = fn
|
||||
if (reverse == true) {
|
||||
var start = from != null ? from : len - 1
|
||||
for (var i = start; i >= 0; i--) {
|
||||
if (arr[i] == target) return i
|
||||
}
|
||||
} else {
|
||||
var start = from != null ? from : 0
|
||||
for (var i = start; i < len; i++) {
|
||||
if (arr[i] == target) return i
|
||||
}
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
if (reverse == true) {
|
||||
var start = from != null ? from : len - 1
|
||||
for (var i = start; i >= 0; i--) {
|
||||
if (fn(arr[i], i) == true) return i
|
||||
}
|
||||
} else {
|
||||
var start = from != null ? from : 0
|
||||
for (var i = start; i < len; i++) {
|
||||
if (fn(arr[i], i) == true) return i
|
||||
}
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
array.filter = function(arr, fn) {
|
||||
if (!_isArray(arr)) return null
|
||||
if (typeof fn != 'function') return null
|
||||
|
||||
var result = []
|
||||
|
||||
for (var i = 0; i < arr.length; i++) {
|
||||
var val = fn(arr[i], i)
|
||||
if (val == true) {
|
||||
_push.call(result, arr[i])
|
||||
} else if (val != false) {
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
array.sort = function(arr, select) {
|
||||
if (!_isArray(arr)) return null
|
||||
|
||||
var result = _slice.call(arr)
|
||||
var keys = []
|
||||
|
||||
// Extract keys
|
||||
for (var i = 0; i < result.length; i++) {
|
||||
var key
|
||||
if (select == null) {
|
||||
key = result[i]
|
||||
} else if (typeof select == 'string' || typeof select == 'number') {
|
||||
key = result[i][select]
|
||||
} else if (_isArray(select)) {
|
||||
key = select[i]
|
||||
} else {
|
||||
return null
|
||||
}
|
||||
|
||||
if (typeof key != 'number' && typeof key != 'string') return null
|
||||
keys[i] = key
|
||||
}
|
||||
|
||||
// Check all keys are same type
|
||||
if (keys.length > 0) {
|
||||
var keyType = typeof keys[0]
|
||||
for (var i = 1; i < keys.length; i++) {
|
||||
if (typeof keys[i] != keyType) return null
|
||||
}
|
||||
}
|
||||
|
||||
// Create index array and sort
|
||||
var indices = []
|
||||
for (var i = 0; i < result.length; i++) indices[i] = i
|
||||
|
||||
// Stable sort using indices
|
||||
_sort.call(indices, function(a, b) {
|
||||
if (keys[a] < keys[b]) return -1
|
||||
if (keys[a] > keys[b]) return 1
|
||||
return a - b // stable
|
||||
})
|
||||
|
||||
var sorted = []
|
||||
for (var i = 0; i < indices.length; i++) {
|
||||
sorted[i] = result[indices[i]]
|
||||
}
|
||||
|
||||
return sorted
|
||||
}
|
||||
|
||||
return array
|
||||
Reference in New Issue
Block a user