简体   繁体   中英

What is the best way to projecting fields of JavaScript object?

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.

Just 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.com:8080/api/entityA/1" } } }, value: 1, flag: false, _links: { self: { href: "https://example.com:8080/api/entityB/1" } } } ], summerTime: false, parent: { grandParentA: { name: "Grand Parent 0", _links: { self: { href: "https://example.com:8080/api/entityC/1" } } }, grandParentB: null, name: "Parent 0", _links: { self: { href: "https://example.com:8080/api/entityD/1" } } }, _links: { self: { href: "https://example.com: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 comma 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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM