简体   繁体   中英

Using Lodash to create a new object to contain objects in an array with similar property

Is it possible to use Lodash to identify the common values of an array of objects' property and group them together into an object of arrays with the value being set by the common value identified?

Below is an example of a JSON data and Expected outcome.

Because in the future I would like to do something like calculating the total value or the highest value of FavouriteNo

Take note: This is a fake JSON data that I created.

The given JSON data

const arrayOfObj = [
  {
    Name: "John-Code",
    FavouriteNo: 91,
    FavouriteFood: "Pizza"
  },
  {
    Name: "John-Code",
    FavouriteNo: 5,
    FavouriteFood: "Hotdog"
  },
  {
    Name: "Sally-Tan",
    FavouriteNo: 124,
    FavouriteFood: "Ramen"
  },
  {
    Name: "John-Code",
    FavouriteNo: 1,
    FavouriteFood: "Burger"
  },
  {
    Name: "Ash-Charles",
    FavouriteNo: 825,
    FavouriteFood: "Donuts"
  },
  {
    Name: "Sally-Tan",
    FavouriteNo: 129,
    FavouriteFood: "Bread"
  }
];

The expected Arrangement

const expectedArrangement = {
      Code: [
        {
          Name: "John-Code",
          FavouriteNo: 91,
          FavouriteFood: "Pizza"
        },
        {
          Name: "John-Code",
          FavouriteNo: 5,
          FavouriteFood: "Hotdog"
        },
        {
          Name: "John-Code",
          FavouriteNo: 1,
          FavouriteFood: "Burger"
        }
      ],
      Tan: [
        {
          Name: "Sally-Tan",
          FavouriteNo: 129,
          FavouriteFood: "Bread"
        },
        {
          Name: "Sally-Tan",
          FavouriteNo: 124,
          FavouriteFood: "Ramen"
        }
      ],
      Charles: [
        {
          Name: "Ash-Charles",
          FavouriteNo: 825,
          FavouriteFood: "Donuts"
        }
      ]
    };

EDIT: I am planning to use Regex to detect the characters for the Name property

Try this,

 const arrayOfObj = [ { Name: "John-Code", FavouriteNo: 91, FavouriteFood: "Pizza" }, { Name: "John-Code", FavouriteNo: 5, FavouriteFood: "Hotdog" }, { Name: "Sally-Tan", FavouriteNo: 124, FavouriteFood: "Ramen" }, { Name: "John-Code", FavouriteNo: 1, FavouriteFood: "Burger" }, { Name: "Ash-Charles", FavouriteNo: 825, FavouriteFood: "Donuts" }, { Name: "Sally-Tan", FavouriteNo: 129, FavouriteFood: "Bread" } ] const result = arrayOfObj.reduce((acc, val)=>{ const key =val.Name.split("-").pop() acc[key] = acc[key] ? acc[key].concat(val) : [val] return acc }, {}) console.log(result) 

An alternative using vanilla js.

The function reduce helps you to group the objects by the desired key.

 const arrayOfObj = [ { Name: "John-Code", FavouriteNo: 91, FavouriteFood: "Pizza" }, { Name: "John-Code", FavouriteNo: 5, FavouriteFood: "Hotdog" }, { Name: "Sally-Tan", FavouriteNo: 124, FavouriteFood: "Ramen" }, { Name: "John-Code", FavouriteNo: 1, FavouriteFood: "Burger" }, { Name: "Ash-Charles", FavouriteNo: 825, FavouriteFood: "Donuts" }, { Name: "Sally-Tan", FavouriteNo: 129, FavouriteFood: "Bread" }];; var result = arrayOfObj.reduce((a, c) => { // Gets the desired key/name: ie "John-Code" -> "Code" let [_, key] = c.Name.split('-'); /** +--- Checkes if the key/name already exists, if so pushes the current object, * | otherwhise initializes with an empty array and then pushes the current object. * | * | 'a[key] = []' adds a new key/name to the object with a specific value. * | ie: a['Code'] = [] === { Code: [] } * v */ (a[key] || (a[key] = [])).push(c); return a; }, {}); console.log(result); 
 .as-console-wrapper { max-height: 100% !important; top: 0; } 

Using lodash _.groupBy. Group By takes two parameters: the array and a key mapping function. The key function below written without arrow functions

function (itemInArray) {
    return itemInArray.Name.match(/-(.+)/)[1];
}

It is very similar to an Array.map . So the function maps the keys. Then groups the array by those mapped keys.

_.groupBy(arrayOfObj, i => i.Name.match(/-(.+)/)[1])

 const arrayOfObj = [ { Name: "John-Code", FavouriteNo: 91, FavouriteFood: "Pizza" }, { Name: "John-Code", FavouriteNo: 5, FavouriteFood: "Hotdog" }, { Name: "Sally-Tan", FavouriteNo: 124, FavouriteFood: "Ramen" }, { Name: "John-Code", FavouriteNo: 1, FavouriteFood: "Burger" }, { Name: "Ash-Charles", FavouriteNo: 825, FavouriteFood: "Donuts" }, { Name: "Sally-Tan", FavouriteNo: 129, FavouriteFood: "Bread" } ]; console.log(_.groupBy(arrayOfObj, i => i.Name.match(/-(.+)/)[1])) 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/1.2.1/lodash.min.js"></script> 

_.groupBy accept function/string as a second parameter, in case of function it will compare that and group result with the same value (in this case, lastname).

This is another way to archive same goal, but hopefully easier to read & understand.

 const arrayOfObj = [ { Name: "John-Code", FavouriteNo: 91, FavouriteFood: "Pizza" }, { Name: "John-Code", FavouriteNo: 5, FavouriteFood: "Hotdog" }, { Name: "Sally-Tan", FavouriteNo: 124, FavouriteFood: "Ramen" }, { Name: "John-Code", FavouriteNo: 1, FavouriteFood: "Burger" }, { Name: "Ash-Charles", FavouriteNo: 825, FavouriteFood: "Donuts" }, { Name: "Sally-Tan", FavouriteNo: 129, FavouriteFood: "Bread" } ]; const result =_.groupBy(arrayOfObj, member => { const [firstname, lastname] = _.split(member.Name, '-'); return lastname; }); console.log(result); 
 <script src="https://cdn.jsdelivr.net/npm/lodash@4.17.5/lodash.min.js"></script> 

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