Thursday, February 24, 2011

Shuffling Object Properties in JavaScript

Problem:
If you are looking to reorder properties of a JavaScript object (because you may have had an associative array from PHP pass you a json encoded array), you may have found it difficult to do.

Note: I build on my previous method of ActionScript 3.0 Shuffle method. JavaScript and ActionScript are both ECMA languages and have a very similar syntax. The shuffle method I am using below if identical to the one I posted previously.

Solution:
The solution I came up with may not be the most elegant but it gets the job done. It uses a combination of three functions (including the Array shuffle prototype method).

First I started with the JavaScript object that I wanted to shuffle properties for:
var obj = {
        "red":"RED",
        "blue":"BLUE",
        "green":"GREEN",
        "yellow":"YELLOW",
        "purple":"PURPLE"
    };

Next I copied my Array prototype method into the top of the document (note that because it's a prototype method, we are required to define it before using it.
Array.prototype.shuffle = function(){
        for (var i = 0; i < this.length; i++){
            var a = this[i];
            var b = Math.floor(Math.random() * this.length);
            this[i] = this[b];
            this[b] = a;
        }
    }
Now I wrote two new methods to help get the job done. A function called getKeys() which takes an object and extracts the keys returning a simple array of keys for that object.
function getKeys(obj){
        var arr = new Array();
        for (var key in obj)
            arr.push(key);
        return arr;
    }
Last I wrote a method that would put it all together and returned a new object that has shuffled properties. The method first defined a new object that will hold my shuffled properties. Then we use our getKeys function to get all the keys from the object. Then we call the shuffle() method (accessible directly through class prototyping). We iterate through the keys (checking for the property shuffle -which now exists on our object) and by using the same key on both objects, we are able to transfer the key and value to the new object.
function shuffleProperties(obj) {
        var new_obj = {};
        var keys = getKeys(obj);
        keys.shuffle();
        for (var key in keys){
            if (key == "shuffle") continue; // skip our prototype method
            new_obj[keys[key]] = obj[keys[key]];
        }
        return new_obj;
    }
 Now to use this from your program, you can do it like this:
obj = shuffleProperties(obj); // run shuffle
With overwriting our original obj with the returned object from the shuffleProperties() method we can now use our obj as though we had just shuffled the properties around.

Here is the complete code:
var obj = {
        "red":"RED",
        "blue":"BLUE",
        "green":"GREEN",
        "yellow":"YELLOW",
        "purple":"PURPLE"
    };
   
    Array.prototype.shuffle = function(){
        for (var i = 0; i < this.length; i++){
            var a = this[i];
            var b = Math.floor(Math.random() * this.length);
            this[i] = this[b];
            this[b] = a;
        }
    }
   
    obj = shuffleProperties(obj); // run shuffle
   
    function shuffleProperties(obj) {
        var new_obj = {};
        var keys = getKeys(obj);
        keys.shuffle();
        for (var key in keys){
            if (key == "shuffle") continue; // skip our prototype method
            new_obj[keys[key]] = obj[keys[key]];
        }
        return new_obj;
    }
   
    function getKeys(obj){
        var arr = new Array();
        for (var key in obj)
            arr.push(key);
        return arr;
    }
If you have improvements or suggestions, please leave a comment. Thanks!

1 comment:

Ben Tedder said...

Great post. Exactly what I was looking for to shuffle my object.