简体   繁体   中英

lodash pick object fields from array

I have array of objects:

var results= [
    {         
      "_type": "MyType",
      "_id": "57623535a44b8f1417740a13",         
      "_source": {
        "info": {
          "year": 2010,
          "number": "string",             
        },
        "type": "stolen",           
        "date": "2016-06-16T00:00:00",
        "createdBy": "57469f3c71c8bf2479d225a6"            
      }
    }
  ];

I need to select specific fields from array. In result, I want to get the following:

[
    {
        "_id": "57623535a44b8f1417740a13",
        "info": {
            "year": 2010,
            "number": "string"
        },
        "type": "stolen",            
        "date": "2016-06-16T00:00:00",
        "createdBy": "57469f3c71c8bf2479d225a6"
    }
]

As you can see, I want to select _id field and content of _source object. How can I do this with lodash?

I've found .map function, but it doesn't take array of keys: var res = _.map(results, "_source");

You could do:

var mapped = _.map(results, _.partialRight(_.pick, ['_id', 'info', 'type', 'date', 'createdBy']));

A little explanation:

  1. _.map() : Expects a function which takes each item from the collection so that you can map it to something else.
  2. _.partialRight() : Takes a function which will be called later on with the its arguments appended to the end
  3. _.pick() : Gets the path specified from the object.

In plain Javascript you could iterate with Array#map and assemble a new object for each object without mutilation the original object.

 var results = [{ "_type": "MyType", "_id": "57623535a44b8f1417740a13", "_source": { "info": { "year": 2010, "number": "string", }, "type": "stolen", "date": "2016-06-16T00:00:00", "createdBy": "57469f3c71c8bf2479d225a6" } }], res = results.map(function (a) { var o = { _id: a._id }; ["info", "type", "date", "createdBy"].forEach(function (k) { o[k] = a._source[k]; }); return o; }); console.log(res);

I had the same requirement, and the below solution worked best for me.

 let users = [ { "_id": "5ead7783ed74d152f86de7b0", "first_name": "User First name 1", "last_name": "User Last name 1", "email": "user1@example.com", "phone": 9587788888 }, { "_id": "5ead7b780d4bc43fd0ef92e7", "first_name": "User FIRST name 1", "last_name": "User LAST name 1", "email": "user2@example.com", "phone": 9587788888 } ]; users = users.map(user => _.pick(user,['_id','first_name'])) console.log(users)
 <script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.min.js"></script>

 var results = [{ _type: "MyType", _id: "57623535a44b8f1417740a13", _source: { info: { year: 2010, number: "string", }, type: "stolen", date: "2016-06-16T00:00:00", createdBy: "57469f3c71c8bf2479d225a6" } }]; var rootProperty = ['_id'] var innerProperty = '_source' var myArray = _.map(results, result => _(result) .pick(rootProperty) .assign(_.result(result, innerProperty)) .value() ) console.log(myArray)
 .as-console-wrapper { max-height: 100% !important; top: 0; }
 <script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.min.js"></script>

You can map() the result and have each item assign() the _id key-value in an object toegether with the _source object.

results = _.map(results, item => _.assign(
  { _id: item._id }, 
  item._source
));

 var results = [{ "_type": "MyType", "_id": "57623535a44b8f1417740a13", "_source": { "info": { "year": 2010, "number": "string", }, "type": "stolen", "date": "2016-06-16T00:00:00", "createdBy": "57469f3c71c8bf2479d225a6" } }]; results = _.map(results, item => _.assign( { _id: item._id }, item._source )); document.write('<pre>' + JSON.stringify(results, 0, 4) + '</pre>');
 <script src="https://cdn.jsdelivr.net/lodash/4.13.1/lodash.min.js"></script>

You may also choose to write this in plain JS:

result = results.map(item => Object.assign(
  { _id: item._id }, item._source
));

 var results = [{ "_type": "MyType", "_id": "57623535a44b8f1417740a13", "_source": { "info": { "year": 2010, "number": "string", }, "type": "stolen", "date": "2016-06-16T00:00:00", "createdBy": "57469f3c71c8bf2479d225a6" } }]; result = results.map(item => Object.assign( { _id: item._id }, item._source )); document.write('<pre>' + JSON.stringify(result, 0, 4) + '</pre>');

To correctly fulfill the OP's question and for even more complex requirements, the application of a schema and a small lodash mixin is invaluable.

The JavaScript is a little ugly, but it looks swell in CoffeeScript (yes, that was a thing once). The compiled JavaScript is hidden beneath.

_.mixin mapGet: (obj, schema) ->
  result = for row in input
    row_result = {}
    for key, value of schema
      row_result[key] = _.get(row, value)
    row_result

 _.mixin({ mapGet: function(obj, schema) { var key, result, row, row_result, value; return result = (function() { var i, len, results; results = []; for (i = 0, len = input.length; i < len; i++) { row = input[i]; row_result = {}; for (key in schema) { value = schema[key]; row_result[key] = _.get(row, value); } results.push(row_result); } return results; })(); }}); /* The remainer is just the proof/usage example */ var expected, input, schema; input = [{ "_type": "MyType", "_id": "57623535a44b8f1417740a13", "_source": { "info": { "year": 2010, "number": "string" }, "type": "stolen", "date": "2016-06-16T00:00:00", "createdBy": "57469f3c71c8bf2479d225a6" }}]; expected = [{ "_id": "57623535a44b8f1417740a13", "info": { "year": 2010, "number": "string" }, "type": "stolen", "date": "2016-06-16T00:00:00", "createdBy": "57469f3c71c8bf2479d225a6" }]; schema = { "_id": "_id", "info": "_source.info", "type": "_source.type", "date": "_source.date", "createdBy": "_source.createdBy" }; console.log('expected result: ' + JSON.stringify(expected, 0, 4)); console.log('actual result: ' + JSON.stringify(_.mapGet(input, schema), 0, 4));
 <script src="https://cdn.jsdelivr.net/lodash/4/lodash.min.js"></script>

Usage:

schema = {
  "_id"      : "_id",
  "info"     : "_source.info",
  "type"     : "_source.type",
  "date"     : "_source.date",
  "createdBy": "_source.createdBy",
}

_.mapGet(input, schema)

Resultant output:

[{
    "_id": "57623535a44b8f1417740a13",
    "info": {
        "year": 2010,
        "number": "string"
    },
    "type": "stolen",
    "date": "2016-06-16T00:00:00",
    "createdBy": "57469f3c71c8bf2479d225a6"
}]

Note: Complex schema can be more easily described if the source JSON is first converted to a flat, dotted, representation via:

jq [leaf_paths as $path | {"key":$path | join("."), "value":getpath($path) }] |from_entries'

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