array-indexer
Version:
Create indexes based on arrays of objects
118 lines (97 loc) • 2.24 kB
JavaScript
module.exports = index;
/**
*
* @template T
* @param {T[]} array
* @param {string[]} fieldList
* @return { {[k in typeof fieldList[number]]: {[k:string]: T[]}} }
*/
function index (array, fieldList) {
var idx = {}
, val
;
if (this && this.constructor.name == 'Array') {
fieldList = array;
array = this;
}
else if (arguments.length === 0) {
array = [];
}
if (fieldList && fieldList.length) {
if (!Array.isArray(fieldList)) {
fieldList = [fieldList];
}
//pre-seed all of the idx fields so we don't
//have to check when processing each record
fieldList.forEach(function (field) {
idx[field] = {};
});
array.forEach(function (obj) {
fieldList.forEach(function (field) {
val = getKeyValue(obj, field);
val = Array.isArray(val) ? val : [val]
val.forEach(function (v) {
if (!idx[field].hasOwnProperty(v)) {
idx[field][v] = [];
}
idx[field][v].push(obj);
})
});
});
}
else {
//index every field
array.forEach(function (obj) {
Object.keys(obj).forEach(function (field) {
val = obj[field];
//avoid indexing fields whose values are objects
if (typeof val === 'object' && !Array.isArray(val)) {
return;
}
if (!idx.hasOwnProperty(field)) {
idx[field] = {};
}
val = Array.isArray(val) ? val : [val]
val.forEach(function (v) {
if (!idx[field].hasOwnProperty(v)) {
idx[field][v] = [];
}
idx[field][v].push(obj);
})
});
});
}
return idx;
}
function getKeyValue(obj, key, undefined) {
var reg = /\./gi
, subKey
, keys
, context
, x
;
if (reg.test(key)) {
keys = key.split(reg);
context = obj;
for (x = 0; x < keys.length; x++) {
subKey = keys[x];
//the values of all keys except for
//the last one should be objects
if (x < keys.length -1) {
if (!context.hasOwnProperty(subKey)) {
return undefined;
}
context = context[subKey];
}
else {
return context[subKey];
}
}
}
else {
return obj[key];
}
};
module.exports.enableArrayIndexPrototype = function () {
Array.prototype.index = index;
};