0

So theres tons of posts on sorting something like this:

var arr = [{a: 1}, {b: 2}] alphabetically by key, but what if you have something like var arr = [{a: 100}, {a: 50}], what I want is to then say "oh you're the same? lets sort you then by value (which will always be a number).

I am unsure how to do either in lodash or any other similar javascript way.

The end result should be either:

[{b: 2}, {a: 1}] // Keys are different (alphabetical)
// or:
[{a: 50}, {a: 100}] // Keys are the same (lowest to highest)

Everything I have seen on stack overflow becomes a quick mess (code wise), and I was thinking, there are sort methods on lodash, but how exactly do I achieve what I want given the circumstances ??

Any ideas?

Some one asked a good question, are there more keys? Are they only a and b?

There would only be two objects in this array at any given time and yes the keys would only ever be strings, in this case the strings could be anything, cat, dog, mouse, apple, banana ... What ever.

The values will only ever be numbers.

Clearing the air

If the keys match, only sort the array by value, if the keys do not match, only sort the array by key. There will only ever be two objects in this array. Apologies for the misunderstanding.

4
  • Are there only a and b keys? Or are keys known before the sorting? Commented Jul 17, 2017 at 18:58
  • What if the object contain more key-value pairs? Then what key get selected? Commented Jul 17, 2017 at 18:59
  • @ibrahimmahrir Updated the post. There are only ever two, the key is always a string (a valid word) and the value is always a number. Commented Jul 17, 2017 at 19:01
  • Your problem is that you're using the wrong data structure. Consider using something else to make sorting in the desired manner simpler, faster, and easier to reason about. As a start, you could consider a container class which provides the appropriate logic and data for sorting. Commented Jul 17, 2017 at 19:14

3 Answers 3

1

You can use only one function to perform the two types of sorting (works for your case, in which you have only an array with two items, but it is completely generic regarding the array length):

var arr1 = [{a: 30}, {a: 2}];
var arr2 = [{b: 30}, {a: 2}];

function sortArr(arr) {
  return arr.sort((a, b) => {
    var aKey = Object.keys(a)[0];
    var bKey = Object.keys(b)[0];

    return (aKey !== bKey) ? aKey.localeCompare(bKey) : a[aKey] - b[bKey];
  });
}

var sortedArr1 = sortArr(arr1);
var sortedArr2 = sortArr(arr2);

console.log(sortedArr1);
console.log(sortedArr2);

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

Comments

1

In case you always have one property in your objects you can first sort by key using localeCompare and then by value of that property.

var arr = [{b: 2}, {b: 10}, {a: 1}, {c: 1}, {a: 20}]

arr.sort(function(a, b) {
  var kA = Object.keys(a)[0]
  var kB = Object.keys(b)[0]
  return kA.localeCompare(kB) ||  a[kA] - b[kB] 
})

console.log(arr)

Before sorting you can create array of unique keys that you can use to check if all object have the same key by checking if length is > 1 and use that in sort function.

var arr = [{b: 10}, {b: 2}, {a: 1}, {c: 1}, {a: 20}, {b: 22}]
var arr2 = [{a: 10}, {a: 2}, {a: 1}, {a: 22}]


function customSort(data) {
  var keys = [...new Set([].concat(...data.map(e => Object.keys(e))))]

  data.sort(function(a, b) {
    var kA = Object.keys(a)[0]
    var kB = Object.keys(b)[0]

    return keys.length > 1 ? kA.localeCompare(kB) : a[kA] - b[kB]
  })

  return data;
}

console.log(customSort(arr))
console.log(customSort(arr2))

5 Comments

While I like this answer you sort by key and then by value, it has to be either or, for example if the keys match, only sort by value, if the keys don't match only sort by keys. I should have been more clear - I apologize. I updated my post to reflect this.
So if the keys are not the same you don't want to also sort it by value?
@TheWebs this answer does exactly that. If localeCompare returns 0 (means they have the same key) then we should sort by value. a[kA] - b[kB] won't be evaluated unless a and b have the same key.
@TheWebs if localeCompare returns -1 then -1 will be returned. If localeCompare returns 1 then 1 will be returned. If localeCompare returns 0 then a[kA] - b[kB] will be returned
@TheWebs I updated my answer you can see that elements in first array with key b are not sorted by value also just to point out this function just returns reference to original array and also modify it.
0

var arr = [{b: 2}, {a: 1}, {b: 1}, {a: 100}, {a: 20}];

arr.sort(function(a, b) {
  var aKey = a.hasOwnProperty("a")? "a": "b",  // get the first object key (if it has the property "a" then its key is "a", otherwise it's "b")
      bKey = b.hasOwnProperty("a")? "a": "b";  // same for the second object
      
  return aKey === bKey?                        // if the keys are equal
           a[aKey] - b[aKey]:                  // then sort the two objects by the value of that key (stored in either aKey or bKey)
           aKey.localeCompare(bKey);           // otherwise sort by the strings aKey and bKey (the keys of the two objects)
});

console.log(arr);

1 Comment

Looking at it the two arguments of the sort callback a and b and the properties "a" and "b" seems a bit confusing. I hope it's clear :).

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.