Vlad B.
Vlad B.

Reputation: 2937

Nest conditional sorting JavaScript array of objects

I'm trying to achieve nested sorting by some conditions. For example, I have an array of objects:

Array of objects that I have:

    var objArray = [
      {
        total: 2,
        completed: 1,
        created: "2021-03-19T13:09:57.9191082",
      },
      {
        total: 2,
        completed: 0,
        created: "2021-03-19T15:36:32.5761928",
      },
      {
        total: 2,
        completed: 1,
        created: "2021-03-19T15:40:47.1690151",
      },
      {
        total: 3,
        completed: 1,
        created: "2021-03-22T09:33:03.1541255",
      },
      {
        total: 2,
        completed: 1,
        created: "2021-03-23T08:42:45.9854381",
      },
      {
        total: 2,
        completed: 1,
        created: "2021-03-23T09:37:17.8576954",
      },
      {
        total: 22,
        completed: 2,
        created: "2021-03-23T09:40:16.1180247",
      },
      {
        total: 22,
        completed: 21,
        created: "2021-03-23T10:07:13.6602386",
      },
      {
        total: 2,
        completed: 2,
        created: "2021-04-01T08:41:17.2340404",
      },
      {
        total: 2,
        completed: 1,
        created: "2021-04-01T09:33:20.9257699",
      },
      {
        total: 2,
        completed: 2,
        created: "2021-04-01T09:40:13.4354591",
      },
      {
        total: 2,
        completed: 1,
        created: "2021-04-07T07:43:03.8319172",
      },
      {
        total: 4,
        completed: 0,
        created: "2021-04-07T07:50:36.8278655",
      },
      {
        total: 2,
        completed: 2,
        created: "2021-04-07T08:31:05.2998603",
      },
      {
        total: 2,
        completed: 1,
        created: "2021-04-07T08:31:53.3266938",
      },
      {
        total: 3,
        completed: 0,
        created: "2021-04-15T08:18:33.1249212",
      },
      {
        total: 3,
        completed: 1,
        created: "2021-04-15T08:21:25.5196674",
      },
    ];

Array of objects that I'm trying to achieve:

  var objArray = [
    {
        percentage: '0',
        total: 2,
        completed: 0,
        created: '2021-03-19T15:36:32.5761928',
    },
    {
        percentage: '0',
        total: 4,
        completed: 0,
        created: '2021-04-07T07:50:36.8278655',
    },
    {
        percentage: '0',
        total: 3,
        completed: 0,
        created: '2021-04-15T08:18:33.1249212',
    },
    {
        percentage: '95',
        total: 22,
        completed: 21,
        created: '2021-03-23T10:07:13.6602386',
    },
    {
        percentage: '50',
        total: 2,
        completed: 1,
        created: '2021-03-19T13:09:57.9191082',
    },
    {
        percentage: '50',
        total: 2,
        completed: 1,
        created: '2021-03-19T15:40:47.1690151',
    },
    {
        percentage: '50',
        total: 2,
        completed: 1,
        created: '2021-03-23T08:42:45.9854381',
    },
    {
        percentage: '50',
        total: 2,
        completed: 1,
        created: '2021-03-23T09:37:17.8576954',
    },
    {
        percentage: '50',
        total: 2,
        completed: 1,
        created: '2021-04-01T09:33:20.9257699',
    },
    {
        percentage: '50',
        total: 2,
        completed: 1,
        created: '2021-04-07T07:43:03.8319172',
    },
    {
        percentage: '50',
        total: 2,
        completed: 1,
        created: '2021-04-07T08:31:53.3266938',
    },
    {
        percentage: '33',
        total: 3,
        completed: 1,
        created: '2021-03-22T09:33:03.1541255',
    },
    {
        percentage: '33',
        total: 3,
        completed: 1,
        created: '2021-04-15T08:21:25.5196674',
    },
    {
        percentage: '9',
        total: 22,
        completed: 2,
        created: '2021-03-23T09:40:16.1180247',
    },
    {
        percentage: '100',
        total: 2,
        completed: 2,
        created: '2021-04-07T08:31:05.2998603',
    },
    {
        percentage: '100',
        total: 2,
        completed: 2,
        created: '2021-04-01T09:40:13.4354591',
    },
    {
        percentage: '100',
        total: 2,
        completed: 2,
        created: '2021-04-01T08:41:17.2340404',
    },
];

From this array of objects, I'm mapping the object and creating additional key/value 'percentage' to calculate the percentage between total and completed and sort them by the percentage done. Once the sorting by percentage is done I have additional conditions. If the percentage is 100% done sort the 100% done tasks by the 'created' date field. If the percentage is between 1 - 99 order by percentage done and if for example the percentage done between two fields is the same order them by date. Additionally, if the percentage done is 0 then order by asc date.

I have tried this function but cant order the percentage between 1 and 99. Any help with this?

var objArray = [
  {
    total: 2,
    completed: 1,
    created: "2021-03-19T13:09:57.9191082",
  },
  {
    total: 2,
    completed: 0,
    created: "2021-03-19T15:36:32.5761928",
  },
  {
    total: 2,
    completed: 1,
    created: "2021-03-19T15:40:47.1690151",
  },
  {
    total: 3,
    completed: 1,
    created: "2021-03-22T09:33:03.1541255",
  },
  {
    total: 2,
    completed: 1,
    created: "2021-03-23T08:42:45.9854381",
  },
  {
    total: 2,
    completed: 1,
    created: "2021-03-23T09:37:17.8576954",
  },
  {
    total: 22,
    completed: 2,
    created: "2021-03-23T09:40:16.1180247",
  },
  {
    total: 22,
    completed: 21,
    created: "2021-03-23T10:07:13.6602386",
  },
  {
    total: 2,
    completed: 2,
    created: "2021-04-01T08:41:17.2340404",
  },
  {
    total: 2,
    completed: 1,
    created: "2021-04-01T09:33:20.9257699",
  },
  {
    total: 2,
    completed: 2,
    created: "2021-04-01T09:40:13.4354591",
  },
  {
    total: 2,
    completed: 1,
    created: "2021-04-07T07:43:03.8319172",
  },
  {
    total: 4,
    completed: 0,
    created: "2021-04-07T07:50:36.8278655",
  },
  {
    total: 2,
    completed: 2,
    created: "2021-04-07T08:31:05.2998603",
  },
  {
    total: 2,
    completed: 1,
    created: "2021-04-07T08:31:53.3266938",
  },
  {
    total: 3,
    completed: 0,
    created: "2021-04-15T08:18:33.1249212",
  },
  {
    total: 3,
    completed: 1,
    created: "2021-04-15T08:21:25.5196674",
  },
];

var sorted = objArray
  .map((p) => ({ percentage: ((p.completed / p.total) * 100).toFixed(), ...p }))
  .sort((a, b) => {
    if (
      a.percentage == b.percentage &&
      a.percentage == "100" &&
      b.percentage == "100"
    ) {
      return b.created.localeCompare(a.created);
    } else if (a.percentage == b.percentage) {
      return a.created.localeCompare(b.created);
    } else {
      return Number(a.percentage) - Number(b.percentage);
    }
  });

console.log(sorted)

Upvotes: 3

Views: 112

Answers (1)

Nina Scholz
Nina Scholz

Reputation: 386680

You could apply some custom sorting.

const
    objArray = [{ total: 2, completed: 1, created: '2021-03-19T13:09:57.9191082', }, { total: 2, completed: 0, created: '2021-03-19T15:36:32.5761928' }, { total: 2, completed: 1, created: '2021-03-19T15:40:47.1690151' }, { total: 3, completed: 1, created: '2021-03-22T09:33:03.1541255' }, { total: 2, completed: 1, created: '2021-03-23T08:42:45.9854381' }, { total: 2, completed: 1, created: '2021-03-23T09:37:17.8576954' }, { total: 22, completed: 2, created: '2021-03-23T09:40:16.1180247' }, { total: 22, completed: 21, created: '2021-03-23T10:07:13.6602386' }, { total: 2, completed: 2, created: '2021-04-01T08:41:17.2340404' }, { total: 2, completed: 1, created: '2021-04-01T09:33:20.9257699' }, { total: 2, completed: 2, created: '2021-04-01T09:40:13.4354591' }, { total: 2, completed: 1, created: '2021-04-07T07:43:03.8319172' }, { total: 4, completed: 0, created: '2021-04-07T07:50:36.8278655' }, { total: 2, completed: 2, created: '2021-04-07T08:31:05.2998603' }, { total: 2,  completed: 1, created: '2021-04-07T08:31:53.3266938' }, { total: 3, completed: 0, created: '2021-04-15T08:18:33.1249212' }, { total: 3, completed: 1, created: '2021-04-15T08:21:25.5196674' }],
    sorted = objArray
        .map(p => ({ percentage: (p.completed * 100 / p.total).toFixed(), ...p }))
        .sort((a, b) => {
            const
                order = { 0: -1, 100: 1 },
                direction = ((a.percentage !== '100') || -1);

            return (order[a.percentage] || 0) - (order[b.percentage] || 0)
                || b.percentage - a.percentage
                || direction * a.created.localeCompare(b.created);
        });

console.log(sorted);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Upvotes: 1

Related Questions