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!

Thursday, February 3, 2011

Copy Vector in AS3

Problem: 
When dealing with complex datatypes, you will find the normal assignment doesn't work to make a copy as it does with simple datatypes like int, string, etc.
var vec:Vector. = oldVec; // returns the same object - not a copy!
In short, all this does is passes the reference to the complex datatype so that it now has two variables that point to the same data. Therefor manipulating the oldVec variable would reflect in vec and visa vera.
vec.push("hello"); // this is manipulating the object at the reference - in other words, vec and oldVec still contain the same thing including the new string "hello".

Solution:
With some complex objects (generally visual components), there is a 'clone' method available which allows deep copying of the complex datatype so that you have two separate datatypes. Others have written methods which will copy your data. If you are looking for a shallow copy, Vector provided a concat() method which when passed no parameters, returns a copy of your original vector.
var newVec:Vector. = oldVec.concat(); // returns a shallow copy
Note: Shallow copy means that if you have a vector of complex datatypes, only so many depths are copied to the returned vector object. This solution works well for shallow copies of vectors containing simple datatypes (i.e. int, uint, string, etc.).

Wednesday, February 2, 2011

CodeIgniter - Library class not found when upgrading to CI 2.0

Problem: 
If you have recently upgraded your CodeIgniter framework to their recent 2.0 release, you have have run into some issues, that were not covered in the upgrade guide or in the user manual. A specific error I ran into was a file not found when a controller was looking for it's parent class. The parent class happened to be a general Controller file that extended the CI native Controller class (now should be CI_Controller with 2.0). The class I had written called MY_Controller could not be found.

Solution:
After looking around online I finally found the solution. What was failed to be mentioned in the documentation was that your extending class files should be moved from the 'libraries' folder to the new 'core' folder. This solves the issue.

Thanks for this thread for revealing the solution.