sosick
sosick

Reputation: 622

Javascript: How to sort array of objects by multiple fields?

I have a fairly classic case of sorting on many fields at the same time. What is difficult for me is passing data with fields for sorting from a separate array.

const arrayToSort = [
  {
    Country: "Cyprus",
    Date: new Date(2001, 0, 1),
    CreateBy: "William",
  },
  {
    Country: "Belarus",
    Date: new Date(1999, 0, 1),
    CreateBy: "Yuliana",

  },
  {
    Country: "Denmark",
    Date: new Date(2019, 0, 1),
    CreateBy: "Ava",
  },
  {
    Country: "Albania",
    Date: new Date(2000, 0, 1),
    CreateBy: "Zachary",
  }
];

const sortFields = ["Country", "CreateBy", "Date"];
const descending = [true, false, true];

const sortedArray = arrayToSort.sort((a, b) => {
  return arrayToSort.forEach((field, index) => {
    const isDate = !isNaN(Date.parse(a[field]));

    if (isDate) {
      const dateA = new Date(a[field]).getTime();
      const dateB = new Date(b[field]).getTime();

      if (descending[index] && dateA < dateB) {
        return -1;
      }

      if (dateA > dateB) {
        return 1;
      }

      return 0;
    }

    if (descending[index] && a[field] < b[field]) {
      return -1;
    }

    if (a[field] > b[field]) {
      return 1;
    }

    return 0;
  })
})

console.log(sortedArray);

If I had a static number of elements, I would know what to do. What if I do not know the number of fields in the array? Should I use forEach here? When I console.log sortedArray, nothing changed.

Upvotes: 0

Views: 195

Answers (1)

Jamiec
Jamiec

Reputation: 136074

I'd start off with a function which sorts 2 objects by a field and descending bool

const sortBy = (a,b,field,desc) => {
  if(a[field]<b[field]) return desc ? 1 : -1
  else if(a[field]>b[field]) return desc ? -1 : 1
  else return 0;
};

You can then use this in a loop over your sortFields (and descending) arrays:

const arrayToSort = [
  {
    Country: "Cyprus",
    Date: new Date(2001, 0, 1),
    CreateBy: "William",
  },
  {
    Country: "Belarus",
    Date: new Date(1999, 0, 1),
    CreateBy: "Yuliana",

  },
  {
    Country: "Denmark",
    Date: new Date(2019, 0, 1),
    CreateBy: "Ava",
  },
  {
    Country: "Albania",
    Date: new Date(2000, 0, 1),
    CreateBy: "Zachary",
  }
];

const sortFields = ["Country", "CreateBy", "Date"];
const descending = [true, false, true];

const sortBy = (a,b,field,desc) => {
  if(a[field]<b[field]) return desc ? 1 : -1
  else if(a[field]>b[field]) return desc ? -1 : 1
  else return 0;
};

const result = arrayToSort.sort( (a,b) => {
  for(var i=0;i<sortFields.length;i++){
    var res = sortBy(a,b, sortFields[i], descending[i]);
    if(res != 0) return res;    
  }
  return 0;
})

console.log(result);

Upvotes: 1

Related Questions