1

I am building a chat application using socket.io.

I need to create an array to manage the users connected to each chat room.

To start with I need to store the chat room name, and then in that chat room each user and their status.

chat1
     nickname: user1
     status:   admin
     nickname: user2
     status:   none
     nickname: user3
     status:   none

I need it to sort the nicknames in alphabetical order when it is created or when a user is added or deleted. Is this possible?

Jack
  • 167
  • 3
  • 13

1 Answers1

1

What you've described isn't a multidimensional array, it's an array of Objects or Maps. Assuming Objects:

chat1 = [
     { nickname: 'ethelred',
       status:   'admin'},
     { nickname: 'alfred',
       status:   'none' },
     { nickname: 'canute',
       status:   'none' }
  ]

// This is all that's needed for a very simple sort:
chat1.sort((a,b) => a.nickname > b.nickname)

This will sort and give you [{nickname: 'alfred', status: 'none' }, {nickname: 'canute', status: 'none' }, { nickname: 'ethelred', status: 'admin'}]

// You can continue to transform the data,
// for example, just pull the user nicknames:
chat1.sort((a,b) => a.nickname - b.nickname)
     .map(user => user.nickname)

That will sort and then map across the resulting sorted array to give you a list of users in alphabetical order - ['alfred','canute','ethelred'].

Note, this is naïve, you will need better logic in the sort function (what happens with capital letters, numbers, numbers mixed in with letters, &c?). But that function is completely isolated. You just write a separate (dumb) function that knows nothing about your chatroom object, and pass that to sort() with a.nickname and b.nickname as the arguments - chat1.sort(myFunkySortFunction(a.nickname, b.nickname)) (or you inline the logic and don't abstract it, whatever's simplest).

You'll start getting issues if you have a lot of users, as you'll need to run this on every join/leave event. At that point you'll need something a lot more robust.


Edit1:

So when a new person joins, they either get a. .push()-ed onto the original array, or b. you create a new array with the new person's object. When a person leaves, they either a. get removed from the original array, or b. a new array is created that doesn't include them.

When either of those events happen, you could run the sort function. You need to look at the Array.prototype.sort() method. That should literally be the only thing you need.

Note, what I'm suggesting is not very efficient, it will just do the job, and is very simple.


Re the function passed to sort, a.nickname > b.nickname is not going to work very well. A-Z will come before a-z. 'Xerxes' will come before 'albert'. You could do:

chat1.sort(function(a,b) {
  return a.nickname.toLowerCase() > b.nickname.toLowerCase();
})

So that would sort that out. But you've still an issue with more complex names: it's worth looking at something robust like described here: Javascript : natural sort of alphanumerical strings

Basically, what you're doing isn't hard: you just need to make sure that in that callback function, you specify that you're grabbing the nickname property, otherwise it'll try to sort based on the whole object, and return weird incorrect results.


[very late] Edit2

I just realised that you asked how to add and remove. Staying on the same (functional) theme as the rest of the above: to add you can use Array.prototype.concat() to create a new array that includes the extra user. To remove, Array.prototype.filter() will return a new array with a specific user excised.

So add:

current = [
  { nickname: 'ethelred',
    status:   'admin'},
  { nickname: 'alfred',
    status:   'none' },
  { nickname: 'canute',
    status:   'none' }
]

current.concat({ nickname: 'offa', status: 'none' })

// [{ nickname: 'ethelred', status: 'admin'}, { nickname: 'alfred', status: 'none'}, { nickname: 'canute', status: 'none'}, { nickname: 'offa', status: 'none'}]

To remove:

current = [
  { nickname: 'ethelred',
    status:   'admin'},
  { nickname: 'alfred',
    status:   'none' },
  { nickname: 'canute',
    status:   'none' }
]

current.filter({nickname} => nickname !== 'canute')

// [{ nickname: 'ethelred', status: 'admin'}, { nickname: 'alfred', status: 'none'}]
Community
  • 1
  • 1
DanCouper
  • 850
  • 6
  • 15
  • Thanks! What functions do I need to look at to add/remove etc.? i.e. to create as per your example at the top? – Jack Nov 01 '15 at 18:37
  • Added an edit the answer rather than adding comments :) – DanCouper Nov 01 '15 at 19:51
  • Just seen now that I didn't really answer your comment properly: added some more info. Read up on Array prototype methods on MDN: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/prototype – DanCouper Nov 19 '15 at 14:34