3

Consider this:

[{name:'John'},{age:25},{address:'some street'}]

As you can see none of the keys are a consistent name, so I cannot use.

arr.sort((a,b)=> a.consistentKey < b.consistentKey);

How can I go about sorting something like this, by name, and by value?

so the following sorted by key in alphabetical order should be:

[{address:'some street'},{age:25},{name:'John'}]
12
  • Can explain how would you like to sort it? Commented May 1, 2017 at 23:10
  • 2
    Given the objects do not have consistent property names or types, they are not comparable, and I wonder how you would want to sort them at all.
    – Bergi
    Commented May 1, 2017 at 23:11
  • @Kind user Consider that the whole object, what difference would it make?... I am adding random key value pairs to an array, but would like to sort them based on either key, or value... How is this possible?
    – JohnSnow
    Commented May 1, 2017 at 23:17
  • This whole task doesn't make sense to me. What are you trying to build?
    – Thomas
    Commented May 1, 2017 at 23:21
  • @Thomas no offence, but if you can't help me with this part. I doubt you could help me with the entire project.
    – JohnSnow
    Commented May 1, 2017 at 23:22

4 Answers 4

1

If you are thinking of sorting on the basis of key first and then further on values, you can try the following :

var a = [{name:'John'},{age:25},{address:'some street'}];
        
    alert(JSON.stringify(a.sort((a, b) => {
      nameA = Object.keys(a)[0];
      nameB = Object.keys(b)[0];
    
      if (nameA < nameB) {
        return -1;
      }
      if (nameA > nameB) {
        return 1;
      }
    
      // names must be equal
      return 0;
    })));

Here I have considered only one key, but you can always extend it to multiple keys and similarly you can further sort on the basis of values too.

3
  • you mind console.logging the answer? alert just shows [object object]
    – JohnSnow
    Commented May 1, 2017 at 23:22
  • even console will too print object object except that in chrome. I have stringified the content for debugging. The bottom line is that this code should work.
    – binariedMe
    Commented May 1, 2017 at 23:24
  • 1
    console.dir(someObject) will let you unpack the object contents in the console
    – JacobIRR
    Commented May 1, 2017 at 23:30
0

If you extract the key name using Object.keys, then you can get the values you need to perform the comparison:

[{name: 'John'}, {age: 25}, {address:'some street'}].sort((a, b) => {
  const keyA = Object.keys(a)[0]
  const valA = a[keyA]
  const keyB = Object.keys(b)[0]
  const valB = a[keyB]

  if (keyA > keyB) {
    return 1
  } else if (keyA < keyB) {
    return -1
  } else /* equal */ {
   if (valA > valB) {
      return 1
    } else if (valA < valB) {
      return -1
    } else /* equal */ {
      return 0
    }
  }
})
0
0

You can do this with

input.sort((a, b) => {
  const keya = Object.keys(a)[0];
  const keyb = Object.keys(b)[0];

  return keya.localeCompare(keyb) || a[keya].localeCompare(b[keyb]);
});

Using localeCompare is both shorter and more robust in the face of different language locales.

0

Below is the solution I would use. This solution provides a keys only sort, a values only sort, a keys then values sort, and a values then keys sort.

class FunkySort {
  sort (sortType) {
    switch (sortType) {
      case 'keysOnly':
        return data => this._sortByKey(data);
      case 'valuesOnly':
        return data => this._sortByValue(data);
      case 'valuesPrimary':
        return data => {
          data = this._sortByKey(data);
          return this._sortByValue(data);
        };
      case 'keysPrimary':
        return data => {
          data = this._sortByValue(data);
          return this._sortByKey(data);
        };
    }
  }

  _sortByKey (data) {
    return data.sort((a, b) => {
      var keyA = Object.keys(a)[0];
      var keyB = Object.keys(b)[0];
      return keyA < keyB ? -1 : keyA > keyB ? 1 : 0;
    });
  }

  _sortByValue (data) {
    return data.sort((a, b) => {
      // note that in Node >=v7 you could use `Object.values()`, but not in <v7.0
      var valueA = a[Object.keys(a)[0]];
      var valueB = b[Object.keys(b)[0]];
      return valueA < valueB ? -1 : valueA > valueB ? 1 : 0;
    });
  }
}

const dataArr = [{name:'John'},{age:25},{address:'some street'}];
const fs = new FunkySort();
fs.sort('keysPrimary')(dataArr);

Note that fs.sort is a curried function. The first call sets the type of sort to be done, so fs.sort('keysPrimary') returns a function that takes an array of objects and sorts it first by the values, and then by the keys, resulting in an array of objects sorted by key, and if there are multiple objects with the same key, those are sorted by value.

If you don't need this level of flexibility in the type of sort, then just the _sortByKey helper method should suffice.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.