Skip to content

Instantly share code, notes, and snippets.

@AnandPilania
Created March 14, 2023 06:45
Show Gist options
  • Save AnandPilania/e0f8ddbabec3b497eef0f8a9d22ad318 to your computer and use it in GitHub Desktop.
Save AnandPilania/e0f8ddbabec3b497eef0f8a9d22ad318 to your computer and use it in GitHub Desktop.
JS Collection : A port of Laravel Collection
(function () {
let Collection = function (data) {
this.data = data || [];
};
Collection.make = function (data) {
return new Collection(data);
};
Collection.prototype = {
all: function () {
return this.data;
},
avg: function (key = null) {
const count = this.count();
if (count === 0) {
return 0;
} else {
return this.sum(key) / count;
}
},
chunk: function (size) {
const chunks = [];
let index = 0;
while (index < this.data.length) {
chunks.push(this.data.slice(index, size + index));
index += size;
}
return new Collection(chunks);
},
collapse: function () {
const flattened = this.data.reduce((accumulator, currentValue) => {
if (Array.isArray(currentValue)) {
return accumulator.concat(currentValue);
} else {
accumulator.push(currentValue);
return accumulator;
}
}, []);
return new Collection(flattened);
},
combine: function (values) {
const keys = this.data;
const combined = {};
keys.forEach((key, index) => {
combined[key] = values[index];
});
return new Collection(combined);
},
contains: function (value) {
if (Array.isArray(this.data)) {
return this.data.includes(value);
} else {
return Object.values(this.data).includes(value);
}
},
count: function () {
return this.data.length;
},
diff: function (values) {
const diff = this.data.filter((item) => !values.includes(item));
return new Collection(diff);
},
each: function (callback) {
this.data.forEach(callback);
return this;
},
filter: function (callback) {
const filtered = this.data.filter(callback);
return new Collection(filtered);
},
first: function () {
return this.data[0];
},
flatten: function (depth = Infinity) {
const flattened = this.data.reduce((result, item) => {
if (Array.isArray(item) && depth > 0) {
const flattenedSubArray = new Collection(item).flatten(depth - 1).all();
result.push(...flattenedSubArray);
} else {
result.push(item);
}
return result;
}, []);
return new Collection(flattened);
},
flip: function () {
const flipped = {};
Object.entries(this.data).forEach(([key, value]) => {
flipped[value] = key;
});
return new Collection(flipped);
},
forget: function (key) {
delete this.data[key];
return this;
},
get: function (key, defaultValue = null) {
return this.data[key] ?? defaultValue;
},
groupBy: function (callback) {
const grouped = this.data.reduce((result, item) => {
const key = callback(item);
if (!result[key]) {
result[key] = new Collection();
}
result[key].push(item);
return result;
}, {});
return new Collection(grouped);
},
has: function (key) {
return Object.keys(this.data).includes(key);
},
implode: function (glue, key = null) {
if (key) {
return this.pluck(key).all().join(glue);
} else {
return this.data.join(glue);
}
},
intersect: function (values) {
const intersection = this.data.filter((item) => values.includes(item));
return new Collection(intersection);
},
isEmpty: function () {
return this.count() === 0;
},
isNotEmpty: function () {
return !this.isEmpty();
},
keyBy: function (key) {
const keyed = {};
this.data.forEach((item) => {
const value = item[key];
keyed[value] = item;
});
return new Collection(keyed);
},
keys: function () {
const keys = Object.keys(this.data);
return new Collection(keys);
},
last: function () {
return this.data[this.count() - 1];
},
map: function (callback) {
const mapped = this.data.map(callback);
return new Collection(mapped);
},
max: function (key = null) {
if (key === null) {
return Math.max(...this.data);
} else {
return this.pluck(key).max();
}
},
min: function (key = null) {
if (key === null) {
return Math.min(...this.data);
} else {
return this.pluck(key).min();
}
},
pluck: function (key) {
const plucked = this.data.map((item) => item[key]);
return new Collection(plucked);
},
pop: function () {
this.data.pop();
return this;
},
push: function (item) {
this.data.push(item);
return this;
},
reduce: function (callback, initial = null) {
return initial === null ? this.data.reduce(callback) : this.data.reduce(callback, initial);
},
reject: function (callback) {
const rejected = this.data.filter((item) => !callback(item));
return new Collection(rejected);
},
reverse: function () {
const reversed = this.data.slice().reverse();
return new Collection(reversed);
},
shift: function () {
return this.data.shift();
},
sortBy: function (callback) {
const sorted = this.data.slice().sort((a, b) => {
const aKey = callback(a);
const bKey = callback(b);
if (aKey < bKey) return -1;
if (aKey > bKey) return 1;
return 0;
});
return new Collection(sorted);
},
splice: function (index, length = 0, replacement = []) {
const removed = this.data.splice(index, length, ...replacement);
return new Collection(removed);
},
sum: function (key = null) {
if (key === null) {
return this.data.reduce((sum, item) => sum + item, 0);
} else {
return this.pluck(key).sum();
}
},
tap: function (callback) {
callback(this);
return this;
},
toArray: function () {
return this.data.slice();
},
toJson: function () {
return JSON.stringify(this.data);
},
toObject: function () {
const obj = {};
for (let i = 0; i < this.data.length; i++) {
const item = this.data[i];
if (typeof item === 'object' && item !== null) {
Object.assign(obj, item);
}
}
return obj;
},
toString: function () {
return this.data.join(', ');
},
unshift: function (item) {
this.data.unshift(item);
return this;
},
when: function (value, callback) {
if (value) {
return callback(this);
} else {
return this;
}
},
};
Array.prototype.collect = function (callback) {
const mapped = (typeof callback === 'function' ? this.map(callback) : this);
return new Collection(mapped);
};
Object.prototype.collect = function (callback) {
const mapped = (typeof callback === 'function' ? Object.keys(this).map((key) => callback(this[key], key)) : this);
return new Collection(typeof callback === 'object' || typeof callback === 'array' ? callback : mapped);
};
let collect;
if (typeof jQuery !== 'undefined') {
(function ($) {
$.Collection = Collection;
collect = d => new $.Collection(d);
})(jQuery);
} else {
collect = d => new Collection(d);
}
})();
console.log(collect({a:'a'}));
console.log(collect([1,2,3,4,5,6]));
console.log([1,2,3,4,5,6].collect());
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment