I have to project some fields of javascript to new object.
for example I have a below object
var obj = { fn : 'Abc',
ln : 'Xyz',
id : 123,
nt : 'Note',
sl : 50000}
and i want new object containing fn and id
var projectedObj = { fn : 'Abc', id : 123 }
on the basis of projection
var projection = { fn : 1, id : 1 }
something like this
var projectedObj = project(obj, projection);
So what is the best way or optimized way to do this.
I have to project some fields of javascript to new object.
for example I have a below object
var obj = { fn : 'Abc',
ln : 'Xyz',
id : 123,
nt : 'Note',
sl : 50000}
and i want new object containing fn and id
var projectedObj = { fn : 'Abc', id : 123 }
on the basis of projection
var projection = { fn : 1, id : 1 }
something like this
var projectedObj = project(obj, projection);
So what is the best way or optimized way to do this.
Share Improve this question edited Mar 18, 2018 at 17:39 Ravi Sevta asked Mar 15, 2018 at 6:06 Ravi SevtaRavi Sevta 3,0851 gold badge26 silver badges42 bronze badges 2- What do you mean by projection? – Jonas Wilms Commented Mar 15, 2018 at 6:20
- 1 projection means i just want few fields as explained above from existing object. – Ravi Sevta Commented Mar 15, 2018 at 6:35
5 Answers
Reset to default 4Just loop through the projection object and get the keys projected. For example,
function project(obj, projection) {
let projectedObj = {}
for(let key in projection) {
projectedObj[key] = obj[key];
}
return projectedObj;
}
You can use array#reduce
and iterate through all the keys of projection object and based on the key extract the values from the original object and create your new object.
var project = (o, p) => {
return Object.keys(p).reduce((r,k) => {
r[k] = o[k] || '';
return r;
},{});
}
var obj = { fn : 'Abc', ln : 'Xyz', id : 123, nt : 'Note', sl : 50000};
var projection = { fn : 1, id : 1 };
var projectedObj = project(obj, projection);
console.log(projectedObj);
You can also use array#map
with Object#assign
to create your new object.
var project = (o, p) => {
return Object.assign(...Object.keys(p).map(k => ({[k]: o[k]})));
}
var obj = { fn : 'Abc', ln : 'Xyz', id : 123, nt : 'Note', sl : 50000};
var projection = { fn : 1, id : 1 };
var projectedObj = project(obj, projection);
console.log(projectedObj);
You can reduce
your projection
keys returning returning obj
values as:
var obj = { fn : 'Abc', ln : 'Xyz', id : 123, nt : 'Note', sl : 50000}
var projection = { fn : 1, id : 1 }
function project(obj, projection) {
return Object.keys(projection).reduce((a, e) => { a[e] = obj[e]; return a; }, {});
}
console.log(project(obj, projection));
I did it like this. It can handle nested objects, but probably can't handle properties that can be either a value or an object.
let entity = {
timeStamp: "1970-01-01T00:00:00.000Z",
value: 1,
itemList: [
{
amount: 1,
product: {
name: "Product 0",
_links: { self: { href: "https://example.:8080/api/entityA/1" } }
},
value: 1,
flag: false,
_links: { self: { href: "https://example.:8080/api/entityB/1" } }
}
],
summerTime: false,
parent: {
grandParentA: {
name: "Grand Parent 0",
_links: { self: { href: "https://example.:8080/api/entityC/1" } }
},
grandParentB: null,
name: "Parent 0",
_links: { self: { href: "https://example.:8080/api/entityD/1" } }
},
_links: { self: { href: "https://example.:8080/api/entityE/1" } }
};
let entityProjection = {
parent: {
grandParentA: {
_links: { self: { href: false } }
},
grandParentB: {
_links: { self: { href: false } }
},
_links: { self: { href: false } }
},
_links: { self: { href: false } }
}
const project = (object, projection) => {
return Object.keys(projection).reduce((a, e) => ({ ...a, [e]: object[e] ? (projection[e] ? project(object[e], projection[e]) : object[e]) : object[e] }), {});
}
console.log(project(entity, entityProjection));
As an alternative approach of not passing in a projection object but instead listing up the properties to project as a ma separated string, this module can do that. Note that this module supports not object, but arrays.
var linqmodule = (function() {
projection = function(members) {
var membersArray = members.replace(/s/g, "").split(",");
var projectedObj = {};
for (var i = 0; i < this.length; i++) {
for (var j = 0; j < membersArray.length; j++) {
var key = membersArray[j];
if (j === 0) {
projectedObj[i] = {};
}
projectedObj[i][key] = this[i][key];
}
}
return projectedObj;
};
Array.prototype.select = projection;
dumpmethod = function(arrayobj) {
var result = "";
result += "[";
for (var i = 0; i < Object.keys(arrayobj).length; i++) {
var membersArray = Object.keys(arrayobj[i]);
for (var j = 0; j < membersArray.length; j++) {
if (j === 0) {
result += "{";
}
var key = membersArray[j];
result +=
"key: " +
key +
" , value: " +
arrayobj[i][key] +
(j < membersArray.length - 1 ? " , " : "");
if (j === membersArray.length - 1) {
result +=
"}" + (i < Object.keys(arrayobj).length - 1 ? "," : "") + "\n";
}
}
}
result += "]";
return result;
};
return {
dump: dumpmethod
};
})();
To project your array of Json objects you can then use this example as a guide:
var someCountries = [
{ country: "Norway", population: 5.2, code: "NO" },
{ country: "Finland", population: 5.5, code: "SU" },
{ country: "Iceland", population: 0.4, code: "IC" },
{ country: "Sweden", population: 10.2, code: "SW" }
];
var result = someNums.select("country,population");
console.log(linqmodule.dump(result));
And the resulting array then contains the projected result (and copied into a new array) without the field 'code'.
This does not answer the question, as it asked about a single object and a projection object, but it shows how to achieve the same with an array of objects (having the same fields in each object of the array). So many will then find it useful for similar scenarios.