最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

optimization - What is the best way to projecting fields of JavaScript object? - Stack Overflow

programmeradmin3浏览0评论

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
Add a ment  | 

5 Answers 5

Reset to default 4

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.: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.

发布评论

评论列表(0)

  1. 暂无评论