1

I have a collection of objects in JavaScript like this:


Object collection = new Object();
collection[123] = new Item(); //another object
collection[425] = new Item();
collection[2134] = new Item();
//etc. etc.

//TODO: sort items

I would like to sort this collection according to the properties of the Item objects in collection. There is good built-in sort function in JS Array, so my first idea was to modify the code followingly:


Object collection = new Array();
collection[123] = new Item(); //another object
collection[425] = new Item();
collection[2134] = new Item();
//etc. etc.

collection.sort(comparisonFunction); //where comparisonfunction handles the sorting logic

Now the collection is nicely sorted - however, I cannot access the items using the property, which I used to set them, i.e.


collection[2134]

is null, because the JS array does not contain that many elements (and even if it would, the result would not be as expected)

What I need is the

  • ability to access elements in collection directly with the numerical property I set them (which is already a given, when not using a JS Array)
  • ability to sort the items in the collection

Edit: the object does not need to behave like an array and it is not an array of nature. What I need is pretty close to Java TreeMap - a collection, which maintains a specific order, and which is also a map. Or explained in another way, I need a plain old JavaScript object (which some people know as "associative array") whose contained user-created elements can be sorted.

Edit 2: the solution I ended up using is Anatoliy's, slightly modified. Basically I create an array, where I duplicate the "collection" and map the two objects (array and collection) to get the benefits of both. Also thanks to Roatin Marth for pointing out that iterating objects are not guaranteed to happen in any kind of order (I did consider this when modifying Anatoliy's solution).

simon
  • 12,666
  • 26
  • 78
  • 113
  • What does `comparisonFunction` sort on? – Roatin Marth Oct 05 '09 at 15:18
  • SO your result is collection[0] collection[1] collection[2] but you want it to be collection[123] collection[425] collection[2134]? – jantimon Oct 05 '09 at 15:20
  • What underlying data structure supports your "collection-which-is-not-an-array"? Why not just underpin this collection with an array? – Matt Ball Oct 05 '09 at 15:21
  • Each Item object has an id in form of "4.2.6.3", and it returns 0, a positive value or a negative value according to the id, which the Array.sort function uses to sort the items accordingly. In a similar way as in this example: http://developer.spikesource.com/blogs/vsrini/2007/08/javascript_array_sort_with_cus.html – simon Oct 05 '09 at 15:23
  • Matt Ball: explaining the data structure would take more space than fits into this comment field. Anyway, the reason I cannot use an array is that the numerical properties of the "collection" object are erased when creating an array instead of object, because the array object itself uses numerical properties to store and handle the array values. – simon Oct 05 '09 at 15:29
  • This looks like Java, not JavaScript... – James Oct 05 '09 at 15:34

4 Answers4

8

Where to start...

The last point is key to your question. IMHO you need to change your data type from an Object to an Array (that can maintain a sorted order, thus the sort method available).

Community
  • 1
  • 1
Roatin Marth
  • 23,589
  • 3
  • 51
  • 55
  • Agreed, that code needs to be refactored and you should not try to hack away and do something the language does not natively support. – meder omuraliev Oct 05 '09 at 15:36
  • That's a great summary of my problem, which I failed to put through in my original question. What I'm looking for is basically something similar to Java TreeMap, but in JavaScript. – simon Oct 05 '09 at 15:40
  • The object I have is not an array of nature, and it does not need to maintain order - I just need to have it sorted. And surely it is possible to create an object where iterating objects in order it's possible, I just don't want to reinvent the wheel. – simon Oct 06 '09 at 07:31
2

I think that you need to separate collection into two variables with one as an array and the other as an object. You can probably create a function for your object such that you can call only one function to set both your object var and your array var.

var objects = {};
var collection = [];

objects.set = function(index, data){
  collection[index] = data;
  this[index] = data;
}

objects.set(10, new Item());
objects.set(11, new Item());

collection.sort();
devpl
  • 204
  • 1
  • 2
1

Here is the untested code (just idea):

var arr = [];
for (var i in collection) {
    collection[i].index = i;
    arr.push(collection[i]);
}
arr.sort(f);
var sorted_collection = {};
for (var j in arr) {
    sorted_collection[arr[j].index] = arr[j];
}
Anatoliy
  • 29,485
  • 5
  • 46
  • 45
0

If you don't mind using a JS library like prototype.js...

http://api.prototypejs.org/language/hash.html

Rake36
  • 992
  • 2
  • 10
  • 17