1 2 3 4 5 6 7 8 9 10 11
//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 !
Scott Robinson
December 6, 2007, December 06, 2007 13:06, permalink
x = new Array();
x[2] = 'something';
x[7] = 'somethingelse';
x[99] = 'thelastone';
return x[x.length - 1];
jojolapine
December 6, 2007, December 06, 2007 16:26, permalink
Hello,
I think your solution will not function.
Your example will return the string "thelastone", or I want to get the number 99....
Emmett
December 7, 2007, December 07, 2007 01:42, permalink
Scott's solution is correct, but if you want it as a function...
1 2 3
function lastKey(arr){ return arr[arr.length - 1]; }
Sedril
December 7, 2007, December 07, 2007 07:21, permalink
He want the key, so you where not to far... Here 99.
1 2 3
function getLastKey(arr){ return (arr.length - 1); }
jojolapine
December 7, 2007, December 07, 2007 09:37, permalink
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...
V
December 7, 2007, December 07, 2007 11:24, permalink
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.
Andre Steenveld
December 10, 2007, December 10, 2007 12:33, permalink
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
The Map and some additional stuff
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122
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 ]"; } }); }; })();
Bunch of (sloppy) unit tests
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126
<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>
Kalpesh
December 17, 2007, December 17, 2007 18:51, permalink
You can make an array of array to achieve this thing.
Please look at the code below.
Hope that helps.
1 2
var d = [[1,"hello"], [2,"world"], [99,"test"]]; alert(d[d.length-1][0]);
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 ;)