0

I have the following object:

 events: {
  "123" : {}
  "1234": {} 
}

How can I delete the last X items? for example, in the above example, I would like to delete 2 last items

I know I can use a splice for array but how to do that in an object of objects? thanks

** update ***

I am looking for an efficient way to remove from last and not for each all keys

for example

     events: {
      "123" : {}
      "1234": {} 
      "333": {} 
       "444": {} 
    }

if the number is 2 I will run from the last item and get the 2 objects and will delete them

Tuz
  • 1,106
  • 13
  • 41
  • It would be useful if you posted your code. What have you tried so far> – E. Maggini Jul 05 '20 at 20:36
  • 1
    This is an [XY problem](http://xyproblem.info/) since object order is not guaranteed. Use arrays or Map if you want guaranteed order – charlietfl Jul 05 '20 at 20:38
  • 1
    @charlietfl The object keys iteration order does follow exact rules: https://stackoverflow.com/questions/5525795/does-javascript-guarantee-object-property-order – iota Jul 05 '20 at 20:39
  • @hev1 Sure and with regard to numeric keys they end up in numeric sort order when iterating so which are the last two....last added or highest values? – charlietfl Jul 05 '20 at 20:44
  • thanks , found another solution using array but yes it works – Tuz Jul 06 '20 at 09:29

2 Answers2

2

You can iterate backwards over Object.keys and use the delete operator.

var events = {
  "123" : {},
  "1234": {} 
};
function delLast(obj, num){
  Object.keys(obj).slice(-num).forEach(key=>delete obj[key]);
}
delLast(events, 2);
console.log(events);//{}
events = {
  "123" : {},
  "1234": {} ,
  "12345": {},
  "123456": {},
  "1234567": {}
};
delLast(events, 3);
console.log(events);//{"123": {}, "1234": {}}

However, the iteration order for object keys is only insertion order for non-numeric keys and ascending order for numeric ones. Thus, it will be better to use a Map if you always want the keys in insertion order.

const events = new Map;
events.set("555", {});
events.set("123", {});
events.set("1234", {});
function delLast(map, num){
  [...map.keys()].slice(-num).forEach(key=>map.delete(key));
}
delLast(events, 2);
events.forEach((v,k)=>console.log(k,"=>",v));//555 => {}
iota
  • 34,586
  • 7
  • 32
  • 51
  • Change to `var events = { "555":{},"123" {},"1234": {}};` and result is `{"123":{}}` which is not intuitive – charlietfl Jul 05 '20 at 20:52
  • @charlietfl You're right; I have updated my answer. – iota Jul 05 '20 at 21:07
  • Your iteration order explanation should help OP understand the issue regarding what looks like last may not be what gets removed – charlietfl Jul 05 '20 at 21:11
  • @hev1 thanks. i updated the question - can I do it in an efficient way? because it happens every few seconds, for example, run from the last item – Tuz Jul 06 '20 at 06:23
  • @Tuz What makes you think this way is inefficient? It is `O(n)`. – iota Jul 06 '20 at 13:18
-1

Use Object.entries and then loop through with a delete

events= {
  "123" : {},
  "1234": {} 
}

for (o of Object.entries(events)){
  delete events[o[0]]
}
console.log(events)
Sven.hig
  • 4,315
  • 2
  • 5
  • 18
  • This is also subject to numeric sort order of the keys so last in may not be first removed depending on key value – charlietfl Jul 05 '20 at 21:13