Shoutbox

[?] Sort array by keys... - Printable Version

-Shoutbox (https://shoutbox.menthix.net)
+-- Forum: MsgHelp Archive (/forumdisplay.php?fid=58)
+--- Forum: Messenger Plus! for Live Messenger (/forumdisplay.php?fid=4)
+---- Forum: Scripting (/forumdisplay.php?fid=39)
+----- Thread: [?] Sort array by keys... (/showthread.php?tid=95094)

[?] Sort array by keys... by whiz on 07-23-2010 at 06:30 PM

Say I had an array like this (in its practical use, the objects would have data in, but for this example, I don't really need that).

Javascript code:
var MyArr = [];
MyArr["X"] = {};
MyArr["Z"] = {};
MyArr["W"] = {};
MyArr["Y"] = {};


If I loop through that, it'll go in the written order (X, Z, W, Y).  Is there a relatively simple way of sorting the keys alphabetically (like the PHP ksort() function)?
RE: [?] Sort array by keys... by roflmao456 on 07-23-2010 at 07:01 PM

Try

JScript code:
MyArr.sort();

?
http://www.javascriptkit.com/javatutors/arraysort.shtml

edit: i think it only sorts  the values, not keys..
I guess just find out how to get the key name from a JS array, put them in an array and use the sort function then make a new array (blah):P
RE: [?] Sort array by keys... by Adeptus on 07-23-2010 at 07:12 PM

This kind of a collection is called an associative array or a hash.

What you do is take all your keys and put them as values in another array, which you can then sort.  Then you iterate through the sorted key values and use them as index to the original array, the net result being iterating the original array ordered by the keys' values.  If you want the original array permanently sorted, you can rebuild it while doing this.

For an example, see here.


RE: [?] Sort array by keys... by Eljay on 07-23-2010 at 07:13 PM

Objects can't be sorted by any built-in function that I know of. If you just need to access them in order you can create a separate array containing just the keys and sort that.

JScript code:
var MyObj = {}; // Define empty object
MyObj["X"] = 'bbbb';
MyObj["Z"] = 'dddd';
MyObj["W"] = 'aaaa';
MyObj["Y"] = 'cccc';
 
// Put keys in array and sort
var keyArray = [];
for(key in MyObj) keyArray.push(key);
keyArray.sort();
 
// Loop through object using keyArray order
for(var i=0; i<keyArray.length; ++i)
    Debug.Trace(MyObj[keyArray[i]]);


It really depends what you want to do with the values and why they need to be in a particular order.
RE: [?] Sort array by keys... by whiz on 07-23-2010 at 07:18 PM

That's kind of what I've thought.  :P  I can't test it now, but this should work, right?

Javascript code:
var Arr = [];
// yeah, we know there's stuff in it
var Sort = [];
for (var K in Arr)
{
    Sort.push(K);
}
Sort.sort();
var New = [];
for (var X in Sort)
{
    New[Sort[X]] = Arr[Sort[X]];
}


Edit: no, that's wrong!  ;)  There.
RE: [?] Sort array by keys... by Matti on 07-30-2010 at 07:47 PM

JScript arrays can't have strings as keys, you're just extending the Object instance with W, X, Y and Z properties. They're not actually array elements, you can easily see this when you check MyArr.length (it'll still be 0).

As for sorting object properties, I see two possible solutions. You could create a new object and define the properties in the sorted order, as Eljay proposed. Or you could keep the same object and delete the properties with delete MyObj[K] and then re-add the properties. This preserves prototypes as you're working on the same object you started with.

However, like Eljay I also wonder why you'd need to do this anyway. Objects are great to retrieve a value by its key name and store values with their keys. The order of those values is not important for these tasks since objects don't and shouldn't behave like ordered lists. If you really need hashes with sorting behavior, you might be better off creating something like a custom sorted hash table class with getter/setter and enumerator methods.


RE: [?] Sort array by keys... by whiz on 07-31-2010 at 09:46 AM

I'm using it for Interface Writer, so that windows can be sorted alphabetically.  The data's stored like this:

Javascript code:
Interface.Window[WndId].Property = Value;
Interface.Window[WndId].Control[CtrlId].Property = Value;
Interface.Window[WndId].Element[ElmtId].Property = Value;

I'm looping through the window, control and element arrays.
RE: [?] Sort array by keys... by Matti on 07-31-2010 at 12:56 PM

In that case, you might be better off with what I suggested in my previous post:

quote:
Originally posted by Matti
a custom sorted hash table class with getter/setter and enumerator methods
This solution would consist of an object (indexed on window ID) and an array (alphabetically sorted by ID) holding the window objects. These indexes can then be stored in the window objects themselves so you can quickly access them in both caches. I liked this idea, so I decided to try this myself. :P

I created a SortedObjectStore class which lets you retrieve and add objects while taking care of the sorting automatically. It exposes getter/enumeration methods (Get, GetBySortIdx and GetCount) and setter methods (Add, ChangeId, Remove and RemoveAll).
Here's an example of how to use it:
Javascript code:
Interfaces.Window = new SortedObjectStore;
 
var Window = {};
Window.Id = "MyWindow";
Interface.Window.Add(Window);
// MyWindow is now in the cache
 
var Window = Interface.Window.Get("MyWindow");
// Retrieved MyWindow from the cache
 
Interface.Window.ChangeId(Window, "YourWindow");
// Window is now called YourWindow instead of MyWindow
 
Interface.Window.Remove(Window);
// YourWindow is now removed from the cache

Looping through the sorted cache is done with GetBySortIdx and GetCount:
Javascript code:
for(var i=0, len=Interface.Window.GetCount(); i<len; ++i) {
    var Window = Interface.Window.GetBySortIdx(i);
    // Loop logic goes here
}

The class can also be used for controls and elements, just create a new instance of it:
Javascript code:
var MyWindow = {};
MyWindow.Id = "MyWindow";
MyWindow.Control = new SortedObjectStore;
MyWindow.Element = new SortedObjectStore;

or a bit more classy:
Javascript code:
var Window = function(Id) {
    this.Id = Id;
    this.Control = new SortedObjectStore;
    this.Element = new SortedObjectStore;
    Interface.Window.Add(this);
}
var MyWindow = new Window("MyWindow");

Some notes:
  • You may not directly change the Id and SortIdx properties of the stored objects, since these are used by the class. You may only directly change the Id property when the object is not in the store, for example when creating an object to add to the store.
  • Both sorting and retrieval are case-insensitive, they use the lowercase version of the Id property.
  • When an object is removed from the store, its SortIdx is set to -1.
  • The class is not foolproof. There are no validation checks to make sure that the right variable types are passed in as parameters, it just assumes that you're doing it right. It's up to you to implement some checks when working with user inputted data.
The class is attached and should be ready to use. Even if you don't plan to use the code, you may learn something from it.