Reputation: 29846
Is there any Array
method similar to Array.prototype.map
that takes an array and converts it into a key-value object?
Here's an example:
var people = [{name: 'person1', tableId: 1}, {name: 'person2', tableId: 2}];
var table = [{id:1, shape:2, title: 'table1'}, {id:2, shape:4, title: 'table2'}];
I would like to create a table-people object where the key will be an id and the value would be all the people that have the relevant tableId.
An example for the output will be:
var output = {
1: [{name: 'person1', tableId: 1}, <more people>],
2: [{name: 'person2', tableId: 2}}, <more people>]
};
output
will be a key-value object. The key is the tableId and the value is an array of people. A person has some more information(other than name and tableId - this is just a simple example).
Now the easy way to do it is:
var output = {};
for(var i = 0 ; i < table.length ; i++)
{
output[table.id] = getPeopleThatSitInTable(table.id); // will return an array
}
Is there any method like:
table.keyValueMapObject(function(item){
return { key: item.id, value: getPeopleThatSitInTable(item.id) }
});
This method will create an object behind the scenes, fill it based on key & value and return the object?
I'm not looking for something like:
var obj = {}; // declaring an object
// loop somehow and fill obj(for\foreach\map\reduce etc.)
Since using for
does the same thing in "the best way".
I'm looking for something like:
var obj = table.methodName(filterFunction)
Upvotes: 1
Views: 64
Reputation: 2669
I think the most relevant Array method in this case would be reduce
. Though it doesn't help much, you're reducing the table to a key-value object:
var result = table.reduce(function(result, entry) {
result[entry.id] = people.filter(function(person) { // pretty inefficient
return person.tableId === entry.id;
});
return result;
}, {}); // initial key-value object
But actually this use of reduce
is a bit absurd because the callback doesn't really combine two values. It's just modifying and passing the initial object. While it's making the intent clear it's the same as using forEach
:
var result = {}; // initial key-value object
table.forEach(function(entry) {
result[entry.id] = people.filter(function(person) { // pretty inefficient
return person.tableId === entry.id;
});
});
And even then filtering the whole people
array is pretty inefficient. You should only iterate over it once.
var result = {}; // initial key-value object
table.forEach(function(entry) {
result[entry.id] = [];
});
people.forEach(function(person) {
result[person.tableId].push(person);
});
I don't think there's much potential for simplification.
Of course with the power of Object.assign, the spread operator, array comprehensions, computed property names, object destructuring and arrow functions you could write it as follows:
var result = Object.assign({}, ...[{
[id]: people.filter(
({tableId}) => tableId === id
)
} for({id} of table)]);
But it's almost identical to the first version. Again it's inefficient. And it only seems to work in Firefox currently.
I suppose there won't be a native equivalent anytime soon.
Upvotes: 1
Reputation: 147483
The following uses Array.prototype.map, but likely isn't what you want. Consider it just an example of use that might be helpful:
var people = [{name: 'person1', tableId: 1}, {name: 'person2', tableId: 2}];
var obj = {};
people.map(function(v, i) {
var key = v.tableId;
if (!this.hasOwnProperty(key)) {
this[key] = [];
}
this[key].push(v);
}, obj);
Upvotes: 0
Reputation: 1038
You can use forEach
to iterate over tables and construct table-people object by filtering people based on tableId
as follows,
"use strict";
var people = [{name: 'person1', tableId: 1}, {name: 'person2', tableId: 2}];
var table = [{id:1, shape:2, title: 'table1'}, {id:2, shape:4, title: 'table2'}];
var tablePeopleObj = {};
table.forEach(function (tableItem) {
tablePeopleObj[tableItem.id] = getPeople(tableItem.id);
});
function getPeople(tableId) {
return people.filter(function function_name (person) {
return person.tableId == tableId;
});
}
console.log(tablePeopleObj);
Upvotes: 0