0ab5447b6e091c22232b33b0c85bc6f2

I have to get the last key of an associativ array...
I searched a special function, but I don't find it.

ps: I'm so sorry for my english, if you want to refactor it ;)

//creation and affectation
myArray= new Array();
myArray[2]='something';
myArray[7]='somthingelse';
myArray[99]='thelastone';

//my current function
function getLastKey(var a){
    for(var key in a){}
    return key;
}

Refactorings

No refactoring yet !

1945ab4cdb87eaf5a5c906fa884c29f1

Scott Robinson

December 6, 2007, December 06, 2007 13:06, permalink

3 ratings. Login to rate!

x = new Array();
x[2] = 'something';
x[7] = 'somethingelse';
x[99] = 'thelastone';

return x[x.length - 1];

0ab5447b6e091c22232b33b0c85bc6f2

jojolapine

December 6, 2007, December 06, 2007 16:26, permalink

No rating. Login to rate!

Hello,
I think your solution will not function.
Your example will return the string "thelastone", or I want to get the number 99....

D41d8cd98f00b204e9800998ecf8427e

Emmett

December 7, 2007, December 07, 2007 01:42, permalink

2 ratings. Login to rate!

Scott's solution is correct, but if you want it as a function...

function lastKey(arr){
  return arr[arr.length - 1];
}
D41d8cd98f00b204e9800998ecf8427e

Sedril

December 7, 2007, December 07, 2007 07:21, permalink

1 rating. Login to rate!

He want the key, so you where not to far... Here 99.

function getLastKey(arr){
  return (arr.length - 1);
}
0ab5447b6e091c22232b33b0c85bc6f2

jojolapine

December 7, 2007, December 07, 2007 09:37, permalink

No rating. Login to rate!

Hy!!
Your two solutionswill not work... (for me)
Your exemple Emmett will return in my exemple: 'thelastone'
and you Sedril, your solution will return the number 2...
Or I want to get the number 99...
I'm sorry...

D41d8cd98f00b204e9800998ecf8427e

Sedril

December 7, 2007, December 07, 2007 11:04, permalink

1 rating. Login to rate!

Test it, it works fine !

D41d8cd98f00b204e9800998ecf8427e

V

December 7, 2007, December 07, 2007 11:24, permalink

No rating. Login to rate!

You are all reading the code, but not reading the text! He clearly says he wants an associative array, not that it exists in JS, but the closest thing would be the "last" property of an object, hence his use of for..in.
The problem then is: I really am not sure all implementations of javascript will keep and return properties of an object in the same order, always.

D41d8cd98f00b204e9800998ecf8427e

Andre Steenveld

December 10, 2007, December 10, 2007 12:33, permalink

No rating. Login to rate!

V the for...in loop displays quite random behavior and you can't say anything about the "key" you have except that it is a member of the object you are looping through. I have written ( a quick and dirty ) Map class currently i am still writing some unit tests for it but any comments are quite welcome.

Edit Some bug fixes:
- Get elements by index
- Make it work
- added unit tests

Object.extend = function( target, source ){
    var key = "";
    for( key in source ){
        target[ key ] = source[ key ]; }

    return target;
};

var Map = ( function(){

    function getArrayIndex( arr, obj ){
        for( var i = 0; i < arr.length; i++ ){
            if( arr[ i ] === obj ){
                break;
        }    }

        return i;
    }

    // Our little container class, this will be the wrapper for everything we put
    // into the Map object. We want to inform the dev about the key index and that
    // sort of stuff but not let em mess with it...
    var MapItem = function( key, value, items, keys ){
        Object.extend( this, {
            getKey:        function(){ return key; },
            getIndex:      function(){ return getArrayIndex( items, this ); },
            getIndexOfKey: function(){ return getArrayIndex( keys, key ); },

            getValue: function(){ return value; },
            setValue: function( newValue ){
                value = newValue;
                return this;
            }
        });
    };

    // Key map a little class wich can help us keeping the order for the keys...
    var KeyIndexer = {
        create: function( ){
            // IE stupidface won't let me inheret from Array so we need a create method
            // and just rudly overwrite the methods.
            return Object.extend( [ ], {
                // Override the push function so can "push" another key into our collection
                // but istead of just sticking it to the end we will do a little sort first
                // and find the right position. ( Is overriding push() the right course of
                // action here? )
                push: function( key ){
                    for( var i = 0; i < this.length; i++ ){
                        if( /*jsl:ignore*/
                            ( key === this[ i ] )                     // In case we have deplicates
                            || ( i === ( this.length - 1 ) )          // In case we are at the last element
                            || ( key > this[ i ] && key < this[ i ] ) // If we have a real fitting key
                        ){  /*jsl:end*/
                            break;
                        }
                    }

                    this.splice( i, 0, key );

                    return i;
                }
            });
        }
    };

    // The constructor for the Map class here is where the real magic happens.
    return function(){
        // Create some private collections so we can sort all kind of stuff
        var keyArray = KeyIndexer.create( ),
            indexArray = [ ],
            mapObject = { };

        Object.extend( this, {

            add: function( key, value ){
                // Create our item
                var item = new MapItem( key, value, indexArray, keyArray );

                // Add the correct properties and stuff to the collection
                keyArray.push( key.toString() );
                indexArray.push( item );
                mapObject[ key.toString() ] = item;
                return item;
            },
            remove: function( key ){
                var item = this.get( key );

                if( item === null ){ return false; }

                keyArray.splice( item.getIndexOfKey(), 1 );
                indexArray.splice( item.getIndex(), 1 );
                delete mapObject[ key ];

                return true;
            },

            // Some default getters and settings no real magic. If for some
            // reason or another the thing we are looking for is not
            // available we will return null.
            get: function( key ){
                if( typeof key === "string" ){
                    return mapObject[ key ] || null;

                } else if( typeof key === "number" ){
                    return indexArray[ key ] || null;

                }

                return null;
            },

            first: function( ){ return indexArray[ 0 ] || null; },
            last: function( ){ return indexArray[ indexArray.length - 1 ] || null; },

            firstByKey: function( ){ return mapObject[ keyArray[ 0 ] ] || null; },
            lastByKey: function( ){ return mapObject[ keyArray[ keyArray.length - 1 ] ] || null; },

            length: function(){ return keyArray.length; },
            toString: function(){ return "[ Map Object ]"; }
        });
    };
})();
<html>
    <head>
        <script type="text/javascript" src="./map.js"></script>
        <script type="text/javascript">

function createHtmlElement ( elementObj ){
    elementObj = Object.extend({
        tagName: "!--",
        attributes: { },
        innerHTML: " ",
        singelTag: false
    }, elementObj);

    var htmlString = [ "<", elementObj.tagName ];

    for( var attribute in elementObj.attributes ){
        htmlString.push( " " + attribute );
        htmlString.push( attribute.substr(0, 2) === "on" ?
            "=\"(" + elementObj.attributes[attribute].toString() + ")( event );\" " :
            "=\"" + elementObj.attributes[attribute] + "\" " );
    }

    htmlString.push( elementObj.singelTag ? "/>" : ">" );
    htmlString.push( elementObj.innerHTML ); // <-- can be pretty large sometimes...
    htmlString.push( !elementObj.singleTag ? "</" + elementObj.tagName + ">" : "" );

    return htmlString.join("");
}

function observe(element, name, handler) {
    if (element.addEventListener) {
        element.addEventListener(name, handler, false);
    } else {
        element.attachEvent("on" + name, handler);
    }
}

var uniqeId = ( function(){
    var lastId = null;

    return function( ){
        var newId = "uid_" + ( new Date( ) ).getTime( ).toString( 36 );

        lastId = ( newId === lastId ? uniqeId( ) : newId );

        return lastId;
    };
})( );

var myKeys = [ uniqeId(), uniqeId(), uniqeId(), uniqeId() ],
    myValues = [
        { toString: function( ){ return "[ 00 " + myKeys[ 0 ] + " ]"; } },
        { toString: function( ){ return "[ 01 " + myKeys[ 1 ] + " ]"; } },
        { toString: function( ){ return "[ 02 " + myKeys[ 2 ] + " ]"; } },
        { toString: function( ){ return "[ 03 " + myKeys[ 3 ] + " ]"; } }
    ],
    myMap = new Map( );

var results = [
    [ "Creating a new map", myMap instanceof Map ],
    [ "Because it is empty the first should be null", !myMap.first() && !myMap.last() && !myMap.firstByKey() && !myMap.lastByKey() ],
    [ "The map is empty so the length should be 0 aswell", myMap.length() === 0 ]    
];

// Lets continue testing and add a item
myMap.add( myKeys[ 0 ], myValues[ 0 ] );

results.push( [ "The length should now be 1", myMap.length() === 1 ] );
results.push( [ "We should get stuff out now...", !!myMap.first() && !!myMap.last() && !!myMap.firstByKey() && !!myMap.lastByKey() ] );
results.push( [ "Even when look by key.", !!myMap.get( myKeys[ 0 ] ) ] );
results.push( [ "Getting by index.", !!myMap.get( 0 ) ] );

// Add a bunch of objects to the map and test the item object
myMap.add( myKeys[ 2 ], myValues[ 2 ] );
myMap.add( myKeys[ 3 ], myValues[ 3 ] );

results.push( [ "Added some items te map should be 3 big now.", myMap.length() === 3 ] );

results.push( [ "When getting the first item form the map.", myMap.first().getKey() === myKeys[ 0 ] ] );
results.push( [ "The value should be the same aswell", myMap.first().getValue() === myValues[ 0 ] ] );
results.push( [ "The index ofcourse should be 0.", myMap.first().getIndex() === 0 ] );
results.push( [ "And it is the smallest key...", myMap.first().getIndexOfKey() === 0 ] );

results.push( [ "When getting the last item form the map.", myMap.last().getKey() === myKeys[ 3 ] ] );
results.push( [ "The value should be the same aswell", myMap.last().getValue() === myValues[ 3 ] ] );
results.push( [ "The index ofcourse should be 2.", myMap.last().getIndex() === 2 ] );
results.push( [ "And it is the biggest key...", myMap.last().getIndexOfKey() === 2 ] );

results.push( [ "Getting by index and key.", myMap.get( 1 ) === myMap.get( myKeys[ 2 ] ) ] );

// Now for some key magic
myMap.add( myKeys[ 1 ], myValues[ 1 ] );

results.push( [ "The last one pushed..", myMap.last().getValue() === myValues[ 1 ] ] );
results.push( [ "A key wich should fit between 0 and 2", myMap.last().getIndexOfKey() === 1 ] );

observe( window, "load", function(){
    var output = [];

    for( var i = 0; i < results.length; i++ ){
        output.push( "<tr>"
            + "<td>" + results[ i ][ 0 ] + "</td>"
            + "<td style='background-color: " + ( results[ i ][ 1 ] ? "#0F6" : "#F06" ) + "; border: black solid 1px;'>"
              + ( results[ i ][ 1 ] ? "Passed" : "Failed" )
            + "</td></tr>" );            
    }

    document.body.innerHTML = createHtmlElement({
        tagName: "table",
        attributes: {
            style: "border: black solid 1px;"
        },
        innerHTML: createHtmlElement({
            tagName: "tbody",
            innerHTML: output.join( "" )
        })
    });
});

        </script>
    </head>

    <body>
        <!-- stuff goes here -->
    </body>
</html>
Ff71c4381eaf3816bffda6c6fe53d33e

Kalpesh

December 17, 2007, December 17, 2007 18:51, permalink

1 rating. Login to rate!

You can make an array of array to achieve this thing.
Please look at the code below.

Hope that helps.

var d = [[1,"hello"], [2,"world"], [99,"test"]]; 
alert(d[d.length-1][0]);
4d5cf9b8d40af8083b1797aa7c5f3de9

nosredna.myopenid.com

August 22, 2008, August 22, 2008 19:16, permalink

No rating. Login to rate!

The idea that JavaScript has associate arrays is a bit of a misconception. What JavaScript has is an array type that is sort of "bolted on" to its object type.

If you're big on wasting time, you can read my lousy blog posts that deal with objects and arrays:

http://dreaminginjavascript.wordpress.com/2008/08/22/eliminating-duplicates/
http://dreaminginjavascript.wordpress.com/2008/06/27/how-weird-are-javascript-arrays/

Looking at the original post in this thread, jojolapine is using a number as the index of the array in every case, so the replies are completely reasonable. Note that JavaScript always keeps the length property updated to one more than the last index.

For the life of me, I don't know why you're using an array rather than an object. What are you trying to achieve? Why are you using numbers as the indices if you want an associative array rather than a normal array? I think we need to see another example to understand what you're looking for.

By the way, I'm glad you put in the effort to come and ask in English, but you may want to look up "affectation" in the dictionary. It's not all all what you think it is. :-)

64a1736c4d99161054707a2a1393223b

SEO Services

November 8, 2008, November 08, 2008 01:42, permalink

No rating. Login to rate!

Another thing you can do to get the key, if you just want the key and not the value is to do this:

x = new Array();
x[2] = 'something';
x[7] = 'somethingelse';
x[99] = 'thelastone';

return x.length - 1;
B411b84e6f44fa7130b2162247b37e13

Seo Services

October 20, 2009, October 20, 2009 15:02, permalink

No rating. Login to rate!

It is a very nice and good post. Keep up the good work.

B411b84e6f44fa7130b2162247b37e13

Seo Services

October 20, 2009, October 20, 2009 15:03, permalink

No rating. Login to rate!

It is a very nice and good post. Keep up the good work.

B411b84e6f44fa7130b2162247b37e13

Seo Services

October 21, 2009, October 21, 2009 12:31, permalink

No rating. Login to rate!

It is a very nice and good post. Keep up the good work.

Your refactoring





Format Copy from initial code

or Cancel