1

I'm trying to understand why Javascript array sort doesn't work with the following logic. I have no problems making my own algorithm to sort this array, but I'm trying to make it with the Javascript sort built-in method to understand it better.

In this code, I want to push entities that "belongs to" another entity to the bottom, so entities that "has" other entities appear on the top. But apparently, the sort method doesn't compare all elements with each other, so the logic doesn't work properly.

Am I doing something wrong, or it is the correct behavior for the Javascript sort method?

The code I'm trying to execute:

let entities = [
  {
    name: 'Permission2',
    belongsTo: ['Role']
  },
  {
    name: 'Another',
    belongsTo: ['User']
  },
  {
    name: 'User',
    belongsTo: ['Role', 'Permission2']
  },
  {
    name: 'Teste',
    belongsTo: ['User']
  },
  {
    name: 'Role',
    belongsTo: ['Other']
  },
  {
    name: 'Other',
    belongsTo: []
  },
  {
    name: 'Permission',
    belongsTo: ['Role']
  },
  {
    name: 'Test',
    belongsTo: []
  },
]

// Order needs to be Permission, 
let sorted = entities.sort((first, second) => {  
  let firstBelongsToSecond = first.belongsTo.includes(second.name),
    secondBelongsToFirst = second.belongsTo.includes(first.name)
  
  if(firstBelongsToSecond) return 1
  
  if(secondBelongsToFirst) return -1
  
  return 0
})

console.log(sorted.map(item => item.name))

As you can see, "Role" needs to appear before "User", "Other" before "Role", etc, but it doesn't work.

Thanks for your help! Cheers

5
  • 1
    Have you tried debugging your sort function? That should be your first step. Commented Jun 11, 2020 at 16:47
  • Did you remember to read up on developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… to see what positive and negative numbers mean as return value for the comparator? Commented Jun 11, 2020 at 16:47
  • @crashmstr yes, I'm dealing with it for hours... I already know what means -1 and 1 (-1 will send first back, and 1 will send second back)... what I'm trying to understand is if the sort method compares all elements... debugging it seems like it doesn't compare all elements Commented Jun 11, 2020 at 16:50
  • reduce your problem: if you expect user and role to be in a different order, remove the uncertain parts: take out all the elements except for user and role, and see what happens. Then build up the list until things go wrong. Commented Jun 11, 2020 at 16:56
  • 1
    Your missing test is if first or second has an empty belongsTo array. Those come before those that have one or more in their belongsTo array. Commented Jun 11, 2020 at 20:33

1 Answer 1

3

You're running into literally how sorting is supposed to work: sort compares two elements at a time, so let's just take some (virtual) pen and paper and write out what your code is supposed to do.

If we use the simplest array with just User and Role, things work fine, so let's reduce your entities to a three element array that doesn't do what you thought it was supposed to do:

let entities = [
  {
    name: 'User',
    belongsTo: ['Role', 'Permission2']
  },
  {
    name: 'Test',
    belongsTo: []
  },
  {
    name: 'Role',
    belongsTo: ['Other']
  }
]

This will yield {User, Test, Role} when sorted, because it should... so let's see why it should:

  1. pick elements [0] and [1] from [user, test, role] for comparison
  2. compare(user, test)
    • user does not belong to test
    • test does not belong to user
    • per your code: return 0, i.e. don't change the ordering
  3. we slide the compare window over to [1] and [2]
  4. compare(test, role)
    • test does not belong to role
    • role does not belong to test
    • per your code: return 0, i.e. don't change the ordering
  5. we slide the compare window over to [2] and [3]
    • there is no [3], we're done
  6. The sorted result is {user, test, role}, because nothing got reordered

So the "bug" is thinking that sort compares everything-to-everything: as User and Role are not adjacent elements, they will never get compared to each other. Only adjacent elements get compared.

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

1 Comment

Always a good idea to also read through the MDN articles for functions that aren't doing what you expect them to do - most of the time, there's some details you didn't realize were applicable and the docs will give you an "ooooh, okay, of course!" moment.

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.