0

So I have an array of objects similar to below:

var objs = [
  { key: 'address', value: '1234 street' },
  { key: 'nameAndTitle', value: 'John Smith, CEO' },
  { key: 'contactEmail', value: 'johnsmith@gmail.com' },
  { key: 'contactPhone', value: '1234567890' },
  { key: 'localPhone', value: '1234567890' },
  { key: 'status', value: 'open' },
]

And I would like it to be in the same order as another array of strings that I have that looks something like this.

var keys = [
  'nameAndTitle',
  'contactPhone',
  'contactEmail',
  'address',
]

I would like to order the objs array to match the order of the keys array. If the object doesn't exist in the keys array it should be placed at the bottom. Can anyone help me out with this?

Zach Starnes
  • 3,108
  • 9
  • 39
  • 63

4 Answers4

3

You could take the indices and sort by the delta of it.

var objs = [{ key: 'address', value: '1234 street' }, { key: 'nameAndTitle', value: 'John Smith, CEO' }, { key: 'contactEmail', value: 'johnsmith@gmail.com' }, { key: 'contactPhone', value: '1234567890' }],
    keys = ['nameAndTitle', 'contactPhone', 'contactEmail', 'address'];

objs.sort((a, b) => keys.indexOf(a.key) - keys.indexOf(b.key));

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

For haveing complete control over the order, you could take an obejct with values of the wanted order and use a default property with a value smaller than all other values to sort unknown keys to top or with a value greater than all other values to the bottom of the array.

This approach works for fancy sorting scheme as well, where unknown items sorts into the middle, if wanted.

var objs = [{ key: 'localPhone', value: '1234567890' }, { key: 'status', value: 'open' }, { key: 'address', value: '1234 street' }, { key: 'nameAndTitle', value: 'John Smith, CEO' }, { key: 'contactEmail', value: 'johnsmith@gmail.com' }, { key: 'contactPhone', value: '1234567890' }],
    order = { nameAndTitle: 1, contactPhone: 2, contactEmail: 3, address: 4, default: Infinity };

objs.sort(({ key: a }, { key: b }) => (order[a] || order.default) - (order[b] || order.default));

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

ES5

var objs = [{ key: 'localPhone', value: '1234567890' }, { key: 'status', value: 'open' }, { key: 'address', value: '1234 street' }, { key: 'nameAndTitle', value: 'John Smith, CEO' }, { key: 'contactEmail', value: 'johnsmith@gmail.com' }, { key: 'contactPhone', value: '1234567890' }],
    order = { nameAndTitle: 1, contactPhone: 2, contactEmail: 3, address: 4, default: Infinity };

objs.sort(function (a, b) {
   return (order[a.key] || order.default) - (order[b.key] || order.default);
});

console.log(objs);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Nina Scholz
  • 376,160
  • 25
  • 347
  • 392
  • If I were to add some objects to the objs array that were not in the keys array is there any additional step needed to get the ones to show at the top that match and any that are not in the keys array show up at the bottom - I have modified the question for clarity @Nina Scholz – Zach Starnes Mar 14 '19 at 12:59
  • I am using an older version of angularjs so I am unable to use `=>` replacing it with `function() {}` seems to make it not sort correctly. @Nina Scholz – Zach Starnes Mar 14 '19 at 13:21
  • maybe you missed the key or the return statement. please see edit. – Nina Scholz Mar 14 '19 at 13:24
1

You can create a new array pushing the objects in the correct order which will not modify your original array.

If you don't mind about modifying the original array, you could call the sort function that will check out the keys position in the keys array (I'm sure you'll get some answer to help you with these method)

edit @Nina Scholz did it fast ^^

const objs = [{
    key: 'address',
    value: '1234 street'
  },
  {
    key: 'nameAndTitle',
    value: 'John Smith, CEO'
  },
  {
    key: 'contactEmail',
    value: 'johnsmith@gmail.com'
  },
  {
    key: 'contactPhone',
    value: '1234567890'
  },
];

const keys = [
  'nameAndTitle',
  'contactPhone',
  'contactEmail',
  'address',
];

const array = keys.reduce((tmp, x) => {
  const item = objs.find(y => y.key === x);

  if (item) {
    tmp.push(item);
  }

  return tmp;
}, []);

console.log(array);
Orelsanpls
  • 22,456
  • 6
  • 42
  • 69
0

If it is ok to mutate the array, you can use sort function as follows:

var objs = [{
    key: 'address',
    value: '1234 street'
  },
  {
    key: 'nameAndTitle',
    value: 'John Smith, CEO'
  },
  {
    key: 'contactEmail',
    value: 'johnsmith@gmail.com'
  },
  {
    key: 'contactPhone',
    value: '1234567890'
  }
]

var keys = [
  'nameAndTitle',
  'contactPhone',
  'contactEmail',
  'address',
]

objs.sort(function(a, b) {
  return keys.indexOf(a.key) - keys.indexOf(b.key);
});

console.log(objs)
vahdet
  • 6,357
  • 9
  • 51
  • 106
0

You can do something like this:

Loop through string array. Compare the value (nameAndTitle) with the value of the same index of your obj-array. If it doesnt match, search that string in your key-tag in your obj-array and move it to the right index. Thats how I would do it