bier hier
bier hier

Reputation: 22520

How to sort a nested array of objects in javascript?

I have an array of objects:

entities: [
  {
    name: "zBroomsticks PTY",
    id: 34098365,
    entityType: "personal",
    facilities: [
      {
        type: "Home loan",
        account: "032654 987465",
        existing: true,
        modified: "04/12/2018",
        limit: 100000
      },
      {
        type: "Credt card",
        account: "032654 987465",
        existing: false,
        modified: "04/12/2018",
        limit: 200000
      },
      {
        type: "Credt card",
        account: "032654 987465",
        existing: false,
        modified: "04/12/2018",
        limit: 10000
      },
      {
        type: "Credt card",
        account: "032654 987465",
        existing: false,
        modified: "04/12/2018",
        limit: 10000
      }
    ]
  },
  {
    name: "Mr John Doe -3409865, Mrs Jane Doe -34098365",
    id: 34098365,
    entityType: "business",
    facilities: [
      {
        type: "Overdraft",
        account: "032654 987465",
        existing: false,
        modified: "04/12/2018" ,
        limit: 10000
      }
    ]
  },
  {
    name: "Mr Jack",
    id: 34098365,
    entityType: "mixed",
    facilities: [
      {
        type: "Overdraft",
        account: "032654 987465",
        existing: false,
        modified: "04/12/2018",
        limit: 10000
      }
    ]
  }
]

I want to sort this in a specific order:

  1. entity.name: in alphabetical ascending order.

  2. entity.entityType: 1. personal 2. business 3. mixed

  3. entity.facilities.limit: descending order

This is the code I've got so far:

sortData(entities) {
    var order = {
      entityType: { personal: 2, business: 1 }
    };

    return entities.map(ent =>
      entities.sort(
        (a, b) =>
          a.name - b.name ||
          order.entityType[a.facilities.entityType] - order.entityType[b.facilities.entityType]
      )
    );
}

I know how to perform the name sorting but cannot find an approach for 2 & 3?

Link to code

Upvotes: 4

Views: 111

Answers (3)

Shidersz
Shidersz

Reputation: 17190

First, to order by names you can use localeCompare(). Second, there is no property entityType inside the facilities array but you are trying to access it. Now, one solution is to first use Array.map() to get a new array where the facilities array are ordered by the limit property, then you can sort the new array returned by map() first by names and second by the entityType property, something like this:

const input = [{name:"zBroomsticks PTY",id:34098365,entityType:"personal",facilities:[{type:"Home loan",account:"032654 987465",existing:true,modified:"04/12/2018",limit:100000},{type:"Credt card",account:"032654 987465",existing:false,modified:"04/12/2018",limit:200000},{type:"Credt card",account:"032654 987465",existing:false,modified:"04/12/2018",limit:10000},{type:"Credt card",account:"032654 987465",existing:false,modified:"04/12/2018",limit:10000}]},{name:"Mr John Doe -3409865, Mrs Jane Doe -34098365",id:34098365,entityType:"business",facilities:[{type:"Overdraft",account:"032654 987465",existing:false,modified:"04/12/2018",limit:10000}]},{name:"Mr Jack",id:34098365,entityType:"mixed",facilities:[{type:"Overdraft",account:"032654 987465",existing:false,modified:"04/12/2018",limit:10000}]},{name:"Mr Jack",id:34098365,entityType:"personal",facilities:[{type:"Overdraft",account:"032654 987465",existing:false,modified:"04/12/2018",limit:10000}]}];

let order = {
  entityType: {personal:1, business:2, mixed:3}
};

function sortData(entities)
{    
    let limitOrder = entities.map(e =>
    {
        e.facilities.sort((a, b) => b.limit - a.limit);
        return e;
    });

    return limitOrder.sort((a, b) =>
    {
        return a.name.localeCompare(b.name) ||
               order.entityType[a.entityType] - order.entityType[b.entityType];
    });
}

console.log(sortData(input));
.as-console {background-color:black !important; color:lime;}
.as-console-wrapper {max-height:100% !important; top:0;}

Note, I have duplicate the object related to name: "Mr Jack" using a different entityType so you can see how the algorithm performs when there are two objects with equals names.

Upvotes: 3

hoangdv
hoangdv

Reputation: 16127

Sort your array with a order of priority 1, 2 and finally 3

2 condition, you could use a index object to map entityType with their weight.

3 Because you want to sort by descending order, then you have find minimum limit value in facilities list and compare it with other item.

let entities = [
  {
    name: "zBroomsticks PTY",
    id: 34098365,
    entityType: "personal",
    facilities: [
      {
        type: "Home loan",
        account: "032654 987465",
        existing: true,
        modified: "04/12/2018",
        limit: 100000
      },
      {
        type: "Credt card",
        account: "032654 987465",
        existing: false,
        modified: "04/12/2018",
        limit: 200000
      },
      {
        type: "Credt card",
        account: "032654 987465",
        existing: false,
        modified: "04/12/2018",
        limit: 10000
      },
      {
        type: "Credt card",
        account: "032654 987465",
        existing: false,
        modified: "04/12/2018",
        limit: 10000
      }
    ]
  },
  {
    name: "Mr John Doe -3409865, Mrs Jane Doe -34098365",
    id: 34098365,
    entityType: "business",
    facilities: [
      {
        type: "Overdraft",
        account: "032654 987465",
        existing: false,
        modified: "04/12/2018",
        limit: 10000
      }
    ]
  },
  {
    name: "Mr Jack",
    id: 34098365,
    entityType: "mixed",
    facilities: [
      {
        type: "Overdraft",
        account: "032654 987465",
        existing: false,
        modified: "04/12/2018",
        limit: 10000
      }
    ]
  }
];


const entityIndex = { personal: 1, business: 2, mixed: 3 };

let result = entities.sort((a, b) => {
  if (a.name > b.name) return -1;
  if (a.name < b.name) return 1;

  let et = entityIndex[a.entityType] - entityIndex[b.entityType];
  if (et != 0) return et;

  const aMinLimit = Math.min(...a.facilities.map(i => i.limit));
  const bMinLimit = Math.min(...b.facilities.map(i => i.limit));

  return bMinLimit - aMinLimit;

})

console.log(JSON.stringify(result));

Upvotes: 0

Kamil Kiełczewski
Kamil Kiełczewski

Reputation: 92347

try

eType = {personal:1, business:2, mixed:3};

entities.sort((a,b) => {
   if(a.name>b.name) return 1;
   if(a.name<b.name) return -1;

   let et=eType[a.entityType]-eType[b.entityType];
   return et;   
})

entities.forEach(e=> e.facilities.sort((a,b)=> b.limit - a.limit ))

let entities = [
        {
          name: "zBroomsticks PTY",
          id: 34098365,
          entityType: "personal",
          facilities: [
            {
              type: "Home loan",
              account: "032654 987465",
              existing: true,
              modified: "04/12/2018",
              limit: 100000
            },
            {
              type: "Credt card",
              account: "032654 987465",
              existing: false,
              modified: "04/12/2018",
              limit: 200000
            },
            {
              type: "Credt card",
              account: "032654 987465",
              existing: false,
              modified: "04/12/2018",
              limit: 10000
            },
            {
              type: "Credt card",
              account: "032654 987465",
              existing: false,
              modified: "04/12/2018",
              limit: 10000
            }
          ]
        },
        {
          name: "Mr John Doe -3409865, Mrs Jane Doe -34098365",
          id: 34098365,
          entityType: "business",
          facilities: [
            {
              type: "Overdraft",
              account: "032654 987465",
              existing: false,
              modified: "04/12/2018" ,
              limit: 10000
            }
          ]
        },
{
          name: "Mr Jack",
          id: 34098365,
          entityType: "mixed",
          facilities: [
            {
              type: "Overdraft",
              account: "032654 987465",
              existing: false,
              modified: "04/12/2018",
              limit: 10000
            }
          ]
        }
      ];
      
      
eType = {personal:1, business:2, mixed:3};

entities.sort((a,b) => {
   if(a.name>b.name) return 1;
   if(a.name<b.name) return -1;
   
   let et=eType[a.entityType]-eType[b.entityType];
   return et;   
})

entities.forEach(e=> e.facilities.sort((a,b)=> b.limit - a.limit ))

console.log(entities);

Upvotes: 0

Related Questions