oxjs/src/ox/core/Collection.js

223 lines
4.9 KiB
JavaScript
Raw Normal View History

/**
* Collection utilities - ES Module Version
*/
import { typeOf, isObject, isArray, isString, isFunction } from './Type.js';
/**
* Iterate over collections
*/
export function forEach(collection, iterator, that) {
const type = typeOf(collection);
let i, key;
if (type === 'object') {
for (key in collection) {
if (collection.hasOwnProperty(key)) {
if (iterator.call(that, collection[key], key, collection) === false) {
break;
}
}
}
} else if (type === 'array' || type === 'string') {
for (i = 0; i < collection.length; i++) {
if (iterator.call(that, collection[i], i, collection) === false) {
break;
}
}
}
return collection;
}
/**
* Get length of collection
*/
export function len(collection) {
const type = typeOf(collection);
if (type === 'array' || type === 'string') {
return collection.length;
}
if (type === 'object') {
return Object.keys(collection).length;
}
return 0;
}
/**
* Extend objects (similar to Object.assign but deeper)
*/
export function extend(...args) {
let target = args[0] || {};
let deep = false;
let i = 1;
// Check if deep copy
if (typeof target === 'boolean') {
deep = target;
target = args[1] || {};
i = 2;
}
for (; i < args.length; i++) {
const source = args[i];
if (!source) continue;
for (const key in source) {
if (source.hasOwnProperty(key)) {
const src = target[key];
const copy = source[key];
// Prevent infinite loop
if (target === copy) continue;
if (deep && copy && (isObject(copy) || isArray(copy))) {
let clone;
if (isArray(copy)) {
clone = src && isArray(src) ? src : [];
} else {
clone = src && isObject(src) ? src : {};
}
target[key] = extend(deep, clone, copy);
} else if (copy !== undefined) {
target[key] = copy;
}
}
}
}
return target;
}
/**
* Map over collections
*/
export function map(collection, iterator, that) {
const type = typeOf(collection);
const result = [];
forEach(collection, function(value, key) {
result.push(iterator.call(that, value, key, collection));
});
return type === 'string' ? result.join('') : result;
}
/**
* Filter collections
*/
export function filter(collection, iterator, that) {
const type = typeOf(collection);
const result = type === 'object' ? {} : [];
forEach(collection, function(value, key) {
if (iterator.call(that, value, key, collection)) {
if (type === 'object') {
result[key] = value;
} else {
result.push(value);
}
}
});
return type === 'string' ? result.join('') : result;
}
/**
* Find in collection
*/
export function find(collection, iterator, that) {
let result;
forEach(collection, function(value, key) {
if (iterator.call(that, value, key, collection)) {
result = value;
return false; // break
}
});
return result;
}
/**
* Check if every element passes test
*/
export function every(collection, iterator, that) {
let result = true;
forEach(collection, function(value, key) {
if (!iterator.call(that, value, key, collection)) {
result = false;
return false; // break
}
});
return result;
}
/**
* Check if any element passes test
*/
export function some(collection, iterator, that) {
let result = false;
forEach(collection, function(value, key) {
if (iterator.call(that, value, key, collection)) {
result = true;
return false; // break
}
});
return result;
}
/**
* Get keys of object or indices of array
*/
export function keys(collection) {
if (isObject(collection)) {
return Object.keys(collection);
}
if (isArray(collection) || isString(collection)) {
return Array.from({ length: collection.length }, (_, i) => i);
}
return [];
}
/**
* Get values of collection
*/
export function values(collection) {
if (isObject(collection)) {
return Object.values(collection);
}
if (isArray(collection)) {
return [...collection];
}
if (isString(collection)) {
return collection.split('');
}
return [];
}
// Export all functions
export default {
forEach,
len,
extend,
map,
filter,
find,
every,
some,
keys,
values
};