1

I have a nice riddle that I would like to see solved. There might be a better way of doing this and i am open for idea's. I am trying to write an undo function for a canvas drawing app. I have the following object, within it an array with their own objects with three properties.

var allDamages= {};
allDamages['scratch'] = [];
allDamages['scratch'].push({"x":4,"y":6,"index":1});
allDamages['scratch'].push({"x":3,"y":3,"index":2});
allDamages['scratch'].push({"x":9,"y":9,"index":3});
allDamages['scratch'].push({"x":19,"y":39,"index":4});
allDamages['dent'] = [];
allDamages['dent'].push({"x":59,"y":69,"index":5});
allDamages['dent'].push({"x":59,"y":69,"index":9});
allDamages['dent'].push({"x":39,"y":19,"index":6});
allDamages['rip'] = [];
allDamages['rip'].push({"x":20,"y":22,"index":7});
allDamages['rip'].push({"x":100,"y":56,"index":8});

I want to remove the last entry from this array. I want to do this by the property 'index'. So I need to somehow find the entry which has the highest value of the property 'index' and then remove it from the array. What is the best way in doing this?

Greetings,

Robert

Robert
  • 39
  • 7
  • 1
    If array is sorted by index you can use `allDamages['scratch'].pop();` and if not you should iterate over array get element with highest index and then use `allDamages['scratch'].splice(indexOfElement, 1);` Look at [Array splice method](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/splice) and [Array pop](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/pop) – Givi Dec 03 '13 at 11:53
  • The answers I got are close, but don't deliver me the right result. I want to remove just one entry and not all the entries with the highest index property of their domain. So i need to compare the highest index of ["scratch"] with that of ["dent"] and then decide which entry needs to be removed. – Robert Dec 03 '13 at 12:52

6 Answers6

0

allDamages.scratch.length -1 returns the last index for that array.

Edit:

allDamages.scratch.slice(-1).pop() returns the last array item.

And if you just want to remove the last item in your array you should (like Givi said) use the pop() method on a sorted array like so:

allDamages['scratch'].pop()

Edit2:

Because the question wasn't clear for me. This is my final shot at the problem.

var allDamagesInOneArray = [];

for(array in allDamages){
    allDamagesInOneArray.concat(array);//Assuming every key is an array
}

allDamagesInOneArray.sort(function(a,b){
    return a.index - b.index;
});

var lastObj = allDamagesInOneArray.slice(-1).pop(); //element with latest index
A1rPun
  • 16,287
  • 7
  • 57
  • 90
  • In this case you assume that the "index" is incrementing, like in the example – douwe Dec 03 '13 at 11:52
  • @douwe If he is making a undo functionality then I guess he removes the last index. I'll write another solution which covers it completely. Thanks for feedback ;) – A1rPun Dec 03 '13 at 11:55
  • Yeah I think with index he means the index property of the object literal, not the array index. – douwe Dec 03 '13 at 11:59
  • yeah exactly the property value of the property 'index' – Robert Dec 03 '13 at 12:55
  • Besides you only look at 'scratch'. There needs to be a comparison of all (scratch, dent, crack, tear ,etc.) – Robert Dec 03 '13 at 13:03
  • Alright, from the question it looks like you only mean 1 specific array. – A1rPun Dec 03 '13 at 13:13
  • I've simplified my array to: allDamages.push({"x":39,"y":19,"index":6,"type":'dent'}); That way i can use .pop() function in a normal way. Thank you all for the quick response!!! – Robert Dec 03 '13 at 14:44
  • Thanks for accepting! The way you handle your data is better now. – A1rPun Dec 03 '13 at 14:46
0

I think you should create an object that save three your properties. After that you create a stack for undo. Like this:

function yourObject(x,y,index){
   this.x = x; this.y = y; this.index = index;    
}

var yourStack = new Array();

yourStack.push(new yourObject(4, 6, 1));
Ringo
  • 3,795
  • 3
  • 22
  • 37
0

If the highest index in an array is always the last element of the array:

allDamages.scratch = allDamages.scratch.slice(0, allDamages.scratch.length - 1);

This removes the last element of the array

If index is not incrementing or if you always want to remove the latest index, no matter in which of the damages arrays it is (as I'd guess) you can use this function:

var undo = function(input){

    var max= 0;
    var undoType = "";
    var undoIndex = 0;
    for( var type in input ) {
        // type: string

        var locations = input[type];
        // locations: array

        // find the location of the heighest index property.
        for( var i = 0; i < locations.length; i++ ) {
            if( locations[i]["index"] > max) {
                max = locations[i]["index"] ;
                undoType = type;
                undoIndex = index;
            }
        }
    }

    var output = input[type].splice(undoIndex, 1);
    return output;
}

This should remove the element with the largest "index" property from your damage array.

douwe
  • 1,305
  • 10
  • 12
0

First off, store a counter for highest index property found in the objects, and the index of that object within the scratch array.

var highestIndex = -Infinity;
var indexInArray

Then if you're using jQuery:

$.each( allDamages.scratch, function highestIndex( index, object ){
  if( object.index > highestIndex ){
    highestIndex = object.index;
    indexInArray = index;
  }
} );

Or, if not:

for( var indexCounter = 0, indexCounter < allDamages.scratch, indexCounter++ ){
  if( allDamanges.scratch[ indexCounter ].index > highestIndex ){
    highestIndex = allDamages.scratch[ indexCounter ].index;
    indexInArray = indexCounter;
  }
};
Barney
  • 16,181
  • 5
  • 62
  • 76
  • Thank you for the response. This is close. But you don't know if array 'scratch' has the highest 'index' property of the whole object 'allDamages'. – Robert Dec 03 '13 at 13:01
  • @Robert `scratch` is an array in `allDamages`, therefore it's `index` is the number of items it contains. You can run the same methods. I just wrote on `allDamages` itself to see which of its children has the highest index — the principles are the same. – Barney Dec 03 '13 at 13:37
0

Try:

var allDamages= {};
allDamages['scratch'] = [];
allDamages['scratch'].push({"x":4,"y":6,"index":1});
allDamages['scratch'].push({"x":3,"y":3,"index":2});
allDamages['scratch'].push({"x":9,"y":9,"index":3});
allDamages['scratch'].push({"x":19,"y":39,"index":4});
allDamages['dent'] = [];
allDamages['dent'].push({"x":59,"y":69,"index":5});
allDamages['dent'].push({"x":59,"y":69,"index":9});
allDamages['dent'].push({"x":39,"y":19,"index":6});
allDamages['rip'] = [];
allDamages['rip'].push({"x":20,"y":22,"index":7});
allDamages['rip'].push({"x":100,"y":56,"index":8});
var index;
var cnt = 0;
var val;
$.each(allDamages,function(k,v){        
    if(cnt == 0){
        index = highest(v);  //get highest value from each object of allDamages    
        val = k;
    }
    else{
        if(highest(v) > index){
            index = highest(v);
            val = k;
        }
    }
    cnt++;    
});
console.log("highest : "+index+": "+val);
var len = allDamages[val].length;
for(var i=0;i<len;i++){    
    if(allDamages[val][i].index == index){
        allDamages[val].splice(i,1); //remove object having highest value
        break;
    }
}
console.log(allDamages);
function highest(ary) {
    var high = ary[0].index;
    var len = ary.length;
    if(len > 0){
        for(var i=0;i<len;i++){
            if(ary[i].index > high){
                high = ary[i].index;
            }
        }
    }
    return high;
}

DEMO here.

codingrose
  • 15,563
  • 11
  • 39
  • 58
0

I've simplified my array to:

allDamages.push({"x":39,"y":19,"index":6,"type":'dent'});

That way i can use .pop() function in a normal way.

Thank you all for the quick response!!!

Robert
  • 39
  • 7