7

Take, for instance, the following object:

var fruits = {
    "red" : "apple",
    "blue" : "blueberry",
    "yellow" : "banana"
}

I know I can use delete fruits["red"] to remove it by the key name, but how could I delete the object item by the fruit name?

Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
amlane86
  • 668
  • 4
  • 15
  • 24
  • http://stackoverflow.com/questions/9907419/javascript-object-get-key-by-value/9907509#9907509 – jAndy Mar 28 '12 at 15:05
  • i believe mdm's solution is the only way to achieve this functionality, i'm curious to see if anyone has something clever... – jbabey Mar 28 '12 at 15:06

9 Answers9

10

Have you tried something like this?

function deleteByValue(val) {
    for(var f in fruits) {
        if(fruits[f] == val) {
            delete fruits[f];
        }
    }
}

And as per Rocket's comment, you might want to check hasOwnProperty to make sure you aren't deleting members of the object's prototype:

function deleteByValue(val) {
    for(var f in fruits) {
        if(fruits.hasOwnProperty(f) && fruits[f] == val) {
            delete fruits[f];
        }
    }
}
mdm
  • 12,480
  • 5
  • 34
  • 53
  • Is JS not that picky about deleting an item while in the middle of an iterator? (I may just be playing it extra safe, but didn't know if you had an absolute answer). – Brad Christie Mar 28 '12 at 15:07
  • 2
    Shouldn't you check for `hasOwnProperty` inside the `for...in`? – gen_Eric Mar 28 '12 at 15:07
  • @BradChristie it's never been picky for me, a quick test in Chrome's console confirmed that it was happy enough to do this although it may vary from browser to browser. – mdm Mar 28 '12 at 15:09
  • 1
    You should skip the rest of the loop if you found a key, because it won't appear a second time. – YMMD Mar 28 '12 at 15:10
  • 2
    You're deleting by value, not key, and a value could easily appear twice. A key is guaranteed to only appear once. – Jarrett Meyer Mar 28 '12 at 15:15
  • 1
    Oh, that's true. My bad. Sorry! – YMMD Mar 28 '12 at 15:23
1

Don't know if this is efficient in terms of processing but using filter you can get this done in three lines:

var fruits = {
    "red" : "apple",
    "blue" : "blueberry",
    "yellow" : "banana"
}

var appleless_keys = Object.keys(fruits).filter(this_fruit => fruits[this_fruit] !== "apple");
appleless_obj = {};
appleless_keys.forEach(key => appleless_obj[key] = fruits[key]);
console.dir(appleless_obj);

Or as a function:

var fruits = {
    "red" : "apple",
    "blue" : "blueberry",
    "yellow" : "banana"
}

function remove_fruit(fruit_to_remove,fruits){
  var new_keys = Object.keys(fruits).filter(this_fruit => fruits[this_fruit] !== fruit_to_remove);
  new_obj = {};
  new_keys.forEach(key => new_obj[key] = fruits[key]);  
  return new_obj;
}

console.dir(remove_fruit("apple",fruits));
1

Simplified using key deletion,

function stripProperty(o, v) {
    return  (delete o[Object.keys(o).splice(Object.values(o).indexOf(v), 1)])?o:0;
}   

    var fruits = {
        "red" : "apple",
        "blue" : "blueberry",
        "yellow" : "banana"
    }

    function stripProperty(o, v) {
        return  (delete o[Object.keys(o).splice(Object.values(o).indexOf(v), 1)])?o:0;
    }   


    console.log(stripProperty(fruits, 'banana'));

Usage,

var fruits = {
    "red" : "apple",
    "blue" : "blueberry",
    "yellow" : "banana"
}

console.log(stripProperty(fruits, 'apple'))
Arun Panneerselvam
  • 2,263
  • 1
  • 17
  • 24
1
var key = null;
for (var k in fruits){
  if (fruits[k] === 'apple'){
    key = k;
    break;
  }
}
if (key != null)
  delete fruits[key];

Iterate over the object finding the corresponding key, then remove it (if found).

Brad Christie
  • 100,477
  • 16
  • 156
  • 200
0

use this function

function delobj(obj,val){
    for (x in obj) {
        if(obj[x] == val)
        delete obj[x]
    }
    return obj;
}

use like this

delobj(object "object name",string "value of element")
milad nazari
  • 339
  • 3
  • 5
0

what about this one?

function delteByValue(a){
  fruits.foreach( function( k, v ) {
    if (fruits[v] == a){
      delete fruits[k];
    }
  });
}
p0rter
  • 961
  • 2
  • 13
  • 28
0

I think its a good idea to create a function and override the Object.prototype:

/**
 *  @autor Javier Cobos
 *  @param value The value to look for
 *  @return true if founded deleted, false if not
 */        
Object.prototype.removeByValue = function(value){
         var i;
         for(i in this){
            if(this.hasOwnProperty(i))
                if(value === this[i]){
                   delete(this[i]);
                   return true;
                }
         }   
         return false;
        }

// Example
     var fruits = {
        "red" : "apple",
        "blue" : "blueberry",
        "yellow" : "banana"
    }

        fruits .removeByValue("apple");

This way we have a new method for every single Object in our script :)

Javier Cobos
  • 1,172
  • 10
  • 22
  • Extending Object.prototype and Array.prototype create a lot of surface issues in IE<=8 ... Best to add such a method to a utility such as Underscore or jQuery. $.removeByValue = function(object, value) { ... } (note: these problems tend to present themselves dealing with 3rd party scripts, such as google analytics or ads) – Tracker1 Mar 28 '12 at 15:50
  • Maybe you can encapsulate this functionality into the function you are using it to avoid conflicts – Javier Cobos Mar 29 '12 at 06:28
0

I know you have several acceptable answers at this point... I'm going to include a generic function for this...

// NOTE, replace "Object.removePropertyByValue" 
// with say "jQuery.removePropertyByValue" or "_.removePropertyByValue"
// to create a jQuery or Underscore extension.
Object.removePropertyByValue = function(obj, val) {
  //store list of properties to remove
  var propsToRemove = [];

  for (var prop in obj) {
    if (obj.hasOwnProperty(prop) && obj[prop] === val) {
      //save the property name here, deleting while enumerating is a bad idea.
      propsToRemove.push(prop);
    }
  }

  //remove all the items stored.
  while (propsToRemove.length) delete obj[propsToRemove.pop()];
}

From here you should be able to call: Object.removePropertyByValue(fruits, "red");

Tracker1
  • 19,103
  • 12
  • 80
  • 106
  • It's safe to bind a method to the Object constructor, but not safe to extend the Object.prototype (or Array.prototype), as there are a lot of unintended consequences in third party scripts. (looking at you Google) – Tracker1 Mar 28 '12 at 15:59
-1

You can use the splice method

fruits.splice($.inArray("red", fruits), 1);

But this uses jQuery of course.

You can also use this extension:

Array.prototype.remove = function () {
    var what, a = arguments, L = a.length, ax;
    while (L && this.length) {
        what = a[--L];
        while ((ax = this.indexOf(what)) != -1) {
            this.splice(ax, 1);
        }
    }
    return this;
}
CyclingFreak
  • 1,614
  • 2
  • 21
  • 40