19

I have an array of objects which have a property called 'CODE'.

[
  {
   ID: 168,
   NAME: "First name",
   CODE: "AD"
  },
  {
   ID: 167,
   NAME: "Second name",
   CODE: "CC"
  },
  {
   ID: 169,
   NAME: "Third name",
   CODE: "CCM"
  },
  {
   ID: 170,
   NAME: "Fourth name",
   CODE: "CR"
  },
]

How do I order the array by a customized order like:

var item_order = ["CCM","CR","AD","CC"];

Been trying various methods with no success. Please help.

2
  • 1
    Not able to understand the order of the sort Commented Apr 25, 2018 at 17:54
  • Are you saying you want to use var item_order as the array to compare against to determine order? Commented Apr 25, 2018 at 17:55

5 Answers 5

42

You can use the function sort along with the function indexOf.

var array = [  {   ID: 168,   NAME: "First name",   CODE: "AD"  },  {   ID: 167,   NAME: "Second name",   CODE: "CC"  },  {   ID: 169,   NAME: "Third name",   CODE: "CCM"  },  {   ID: 170,   NAME: "Fourth name",   CODE: "CR"  }],
    item_order = ["CCM","CR","AD","CC"];

array.sort((a, b) => item_order.indexOf(a.CODE) - item_order.indexOf(b.CODE));

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

Sign up to request clarification or add additional context in comments.

5 Comments

Yes, but with a caveat about large arrays addressed in the answers from @NinaScholz and myself.
@ScottSauyet yes, but that is out of scope.
Thanks for the answer. I want to order the array by CODE property specifically according to the item_order.
@newb1849 yes, this answer provides what you're looking for.
Do we know that this is out-of-scope? I was assuming that the array might contain many elements with the same CODE value, but that could be wrong. I just can't tell from the question itself. With a large array, there would be O(n * log n) calls to indexOf. If the arrays are small, or even fixed to the same element count as the sort array, clearly there would be no reason for anything more than this solution. And I'm certainly not suggesting that there is anything wrong with it; I just wanted to note its limitations.
12

For huge arrays, I suggest to use an object for the indices.

var array = [{ ID: 168, NAME: "First name", CODE: "AD" }, { ID: 167, NAME: "Second name", CODE: "CC" }, { ID: 169, NAME: "Third name", CODE: "CCM" }, { ID: 170, NAME: "Fourth name", CODE: "CR" }],
    item_order = ["CCM", "CR", "AD", "CC"],
    order = item_order.reduce((r, k, v) => Object.assign(r, { [k]: v }), {});

array.sort((a, b) => order[a.CODE] - order[b.CODE]);

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

Comments

4

If you have to do something like this often, you might write a small utility to help:

const array = [{ ID: 168, NAME: "First name", CODE: "AD" }, { ID: 167, NAME: "Second name", CODE: "CC" }, { ID: 169, NAME: "Third name", CODE: "CCM" }, { ID: 170, NAME: "Fourth name", CODE: "CR" },{ ID: 166, NAME: "Fifth name", CODE: "CCM" }, { ID: 171, NAME: "Sixth name", CODE: "XXX" }, { ID: 172, NAME: "Seventh name", CODE: "CR" }]

const sortOn = (prop, list) => {
  const order = list.reduce((obj, key, idx) => Object.assign(obj, { [key]: idx + 1}), {});
  const getVal = item => order[item[prop]] || Infinity
  
  return (a, b) => getVal(a) - getVal(b)
}

array.sort(sortOn('CODE', ["CCM", "CR", "AD", "CC"]))
console.log(array)

The order object is much like what Nina Scholz suggested. The reason for idx + 1 rather than just idx is to simplify the next line. That line uses Infinity as a way to sort to the end those whose key value is either undefined or not in the sort list. If you want them at the beginning, you can use 0 or -Infinity.

1 Comment

@Mariusz: I would change it a bit today, replacing the reduce/Object.assign bit with Object.fromEntries/map. But the basic idea is pretty useful.
1

You're going to use array.sort(customSort), where:

function customSort(a,b)
{
    a = item_order.indexOf(a.CODE);
    b = item_order.indexOf(b.CODE);

    return a - b;
}

Comments

1

var array = [
  {
   ID: 168,
   NAME: "First name",
   CODE: "AD"
  },
  {
   ID: 167,
   NAME: "Second name",
   CODE: "CC"
  },
  {
   ID: 169,
   NAME: "Third name",
   CODE: "CCM"
  },
  {
   ID: 170,
   NAME: "Fourth name",
   CODE: "CR"
  },
];

var sortOrder =  ["CCM","CR","AD","CC"];

var sorted = array.sort((a, b) => sortOrder.indexOf(a.CODE) - sortOrder.indexOf(a.CODE));

console.log(sorted);

1 Comment

this is wrong! it should be var sorted = array.sort((a, b) => sortOrder.indexOf(a.CODE) - sortOrder.indexOf(b.CODE));

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.