Home > Enterprise >  find min from arrays of objects
find min from arrays of objects

Time:09-01

I have list of statuses where not started is the minimum , followed by submitted and last is complete.

So if we apply the logic on the data since there are 2 status on the current array of object below which are "Not Started" and "Submitted" so the function should return Not Started because not started is the min.

If there is only 1 item in an array then get the only status as a result.

How do we filter the array of objects and get the min based on the order in statuses array. Thanks for any idea.

#currentCode

  getMin(id:number , key:string) {
    
    let data = [
      {
          "id": 14,
          "status": "Submitted",
  
      },
      {
          "id": 15,
          "status": "Not Started",
      }
  ]

    let min = Math.min(...data.map(item => item.status));

    console.log('result' , min)

  }

#order of statuses

  statuses: any[] = [
    { viewValue: 'Not Started', value: 1 },
    { viewValue: 'Submitted', value: 2 },
    { viewValue: 'Complete', value: 3 },
  ]

#sample array of objects - result Not Started

data = [
    {
        "id": 14,
        "status": "Submitted",

    },
    {
        "id": 15,
        "status": "Not Started",
    }
]

#sample array of objects - result Submitted

  data = [
        {
            "id": 14,
            "status": "Submitted",
    
        },
         {
            "id": 17,
            "status": "Complete",
        }
    ]

#sample array of objects - result Complete , since there is only 1 get the only status

  data = [
         {
            "id": 17,
            "status": "Complete",
        }
    ]

CodePudding user response:

You need to look up the status from data in your statuses array.

const data = [
      {
          "id": 14,
          "status": "Submitted",

      },
       {
          "id": 17,
          "status": "Complete",
      }
  ];

const statuses = [
    { viewValue: 'Not Started', value: 1 },
    { viewValue: 'Submitted', value: 2 },
    { viewValue: 'Complete', value: 3 },
  ]

let min = Math.min(...data.map(item => statuses.find(st => st.viewValue === item.status).value));
let minStatus = statuses.find(st => st.value === min).viewValue;

console.log(minStatus);

CodePudding user response:

A straightforward solution is to simply sort the array by statuses value, which then gives you access to the complete ordering, and the entire object for each position. Here first mapping the statuses array to an object keyed by viewValue to directly access status values.

const data = [
  { "id": 14, "status": "Submitted", },
  { "id": 17, "status": "Complete", },
  { "id": 15, "status": "Not Started", },
  { "id": 15, "status": null, }
];

const statuses = [
  { viewValue: 'Not Started', value: 1 },
  { viewValue: 'Submitted', value: 2 },
  { viewValue: 'Complete', value: 3 },
];
const statusMap = Object.fromEntries(statuses
  .map(({ viewValue, value }) => [viewValue, value])
);

const sorted = data
  .filter(d => Object.hasOwn(statusMap, d.status))
  .sort((a, b) => statusMap[a.status] - statusMap[b.status]);

const min = sorted.at(0);
const max = sorted.at(-1);

console.log('min:', min.status);
console.log('max:', max.status);

// or the complete objects
console.log({ min, max })

Edit

Added a filter() call before sorting to remove datum that don't have a status that appears in statusMap using Object.hasOwn. This also makes the original spread redundant since filter() returns a new array thus avoiding mutation of the original data array with the sort() call.

  • Related