19

how can i remove all the key/value pairs from following map, where key starts with X.

var map = new Object(); 
map[XKey1] = "Value1";
map[XKey2] = "Value2";
map[YKey3] = "Value3";
map[YKey4] = "Value4";

EDIT

Is there any way through regular expression, probably using ^ . Something like map[^XKe], where key starts with 'Xke' instead of 'X'

newbie
  • 251
  • 1
  • 2
  • 7
  • 1
    [`delete`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/delete) with a [`for...in`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for...in) loop – Blazemonger Sep 03 '13 at 18:37
  • @Blazemonger I think their intention is to loop through the array `map` and if the key starts with "x" delete the element. – user1477388 Sep 03 '13 at 18:38
  • @user1477388: then he, she or they need to explain, and clarify, that rather than depending upon guess-work. – David Thomas Sep 03 '13 at 18:43
  • @DavidThomas It was perfectly clear to me, but... Your answer below is good, nice work! – user1477388 Sep 03 '13 at 18:45
  • 1
    Is `XKey1` a variable with a different value? Or are those supposed to be in quotes like `map["XKey1"] = "Value1";`? – Joe Enos Sep 03 '13 at 19:01
  • possible duplicate of [how to remove a key from a JavaScript object?](http://stackoverflow.com/questions/3455405/how-to-remove-a-key-from-a-javascript-object) – Luka Klepec Sep 25 '15 at 07:47
  • It's not a map, it's an object. To delete an item from a real javascript map : var myMap = new Map(); myMap.delete(myKey); – Laurent Jan 30 '21 at 14:47

4 Answers4

18

You can iterate over map keys using Object.key.

The most simple solution is this :

DEMO HERE

Object.keys(map).forEach(function (key) {
 if(key.match('^'+letter)) delete obj[key];
});

So here is an other version of removeKeyStartsWith with regular expression as you said:

function removeKeyStartsWith(obj, letter) {
  Object.keys(obj).forEach(function (key) {
     //if(key[0]==letter) delete obj[key];////without regex
           if(key.match('^'+letter)) delete obj[key];//with regex

  });
}

var map = new Object(); 
map['XKey1'] = "Value1";
map['XKey2'] = "Value2";
map['YKey3'] = "Value3";
map['YKey4'] = "Value4";

console.log(map);
removeKeyStartsWith(map, 'X');
console.log(map);

Solution with Regex will cover your need even if you use letter=Xke as you said but for the other solution without Regex , you will need to replace :

Key[0]==letter with key.substr(0,3)==letter

Charaf JRA
  • 8,249
  • 1
  • 34
  • 44
15

I'd suggest:

function removeKeyStartsWith(obj, letter) {
    for (var prop in obj) {
        if (obj.hasOwnProperty(prop) && prop[0] == letter){
            delete obj[prop];
        }
    }
}

JS Fiddle demo.

Incidentally, it's usually easier (and seems to be considered 'better practice') to use an Object-literal, rather than a constructor, so the following is worth showing (even if, for some reason, you prefer the new Object() syntax:

var map = {
    'XKey1' : "Value1",
    'XKey2' : "Value2",
    'YKey3' : "Value3",
    'YKey4' : "Value4",
};

JS Fiddle demo.

If you really want to use regular expressions (but why?), then the following works:

function removeKeyStartsWith(obj, letter, caseSensitive) {
    // case-sensitive matching: 'X' will not be equivalent to 'x',
    // case-insensitive matching: 'X' will be considered equivalent to 'x'
    var sensitive = caseSensitive === false ? 'i' : '',
        // creating a new Regular Expression object,
        // ^ indicates that the string must *start with* the following character:
        reg = new RegExp('^' + letter, sensitive);
    for (var prop in obj) {
        if (obj.hasOwnProperty(prop) && reg.test(prop)) {
            delete obj[prop];
        }
    }
}

var map = new Object();
map['XKey1'] = "Value1";
map['XKey2'] = "Value2";
map['YKey3'] = "Value3";
map['YKey4'] = "Value4";
console.log(map);
removeKeyStartsWith(map, 'x', true);
console.log(map);

JS Fiddle demo.

Finally (at least for now) an approach that extends the Object prototype to allow for the user to search for a property that starts with a given string, ends with a given string or (by using both startsWith and endsWith) is a given string (with, or without, case-sensitivity:

Object.prototype.removeIf = function (needle, opts) {
    var self = this,
        settings = {
            'beginsWith' : true,
            'endsWith' : false,
            'sensitive' : true
        };
    opts = opts || {};
    for (var p in settings) {
        if (settings.hasOwnProperty(p)) {
            settings[p] = typeof opts[p] == 'undefined' ? settings[p] : opts[p];
        }
    }
    var modifiers = settings.sensitive === true ? '' : 'i',
        regString = (settings.beginsWith === true ? '^' : '') + needle + (settings.endsWith === true ? '$' : ''),
        reg = new RegExp(regString, modifiers);
    for (var prop in self) {
        if (self.hasOwnProperty(prop) && reg.test(prop)){
            delete self[prop];
        }
    }
    return self;
};

var map = {
    'XKey1' : "Value1",
    'XKey2' : "Value2",
    'YKey3' : "Value3",
    'YKey4' : "Value4",
};

console.log(map);
map.removeIf('xkey2', {
    'beginsWith' : true,
    'endsWith' : true,
    'sensitive' : false
});
console.log(map);

JS Fiddle demo.

References:

David Thomas
  • 249,100
  • 51
  • 377
  • 410
  • Thanks is it possible through regular expression, have edited my question. – newbie Sep 03 '13 at 19:14
  • then you will need to user substr – Charaf JRA Sep 03 '13 at 19:39
  • @newbie: no, that wouldn't work as written, but you *could* use `prop.indexOf(letter) === 0` instead. However, while I've yet to add that option in, I've posted a solution which should meet your needs (so far as I understand them at the moment), which extends the `Object` prototype. I'll add references shortly, and explanations (gotta run for a couple chores first, sorry! XD). – David Thomas Sep 03 '13 at 19:42
  • 1
    +1: Nice answer. I find the opts/settings approach a bit over the top and a bit of a kitchen sink and would rather go with multiple methods (or then indeed pass a regex for matching instead), but still... Can't argue you didn't go out of your way to write a nice answer! – haylem Sep 03 '13 at 20:12
  • @haylem: thanks! And yeah I broadly agree with you; but the 'kitchen sink' style of the last iteration was, partially, just in order to try and anticipate further requests (plus I quite like making things easily-extensible, which I *think* that approach is). =) – David Thomas Sep 03 '13 at 20:20
3

You can get it in this way easily.

var map = new Object(); 
map['Key1'] = "Value1";
map['Key2'] = "Value2";
map['Key3'] = "Value3";
map['Key4'] = "Value4";
console.log(map);
delete map["Key1"];
console.log(map);

This is easy way to remove it.

Manindar
  • 999
  • 2
  • 14
  • 30
1

Preconditions

Assuming your original input:

var map = new Object();

map[XKey1] = "Value1";
map[XKey2] = "Value2";
map[YKey3] = "Value3";
map[YKey4] = "Value4";

And Assuming a variable pattern that would contain what you want to keys to be filtered against (e.g. "X", "Y", "prefixSomething", ...).

Solution 1 - Using jQuery to Filter and Create a New Object

var clone = {};

$.each(map, function (k, v) {
  if (k.indexOf(pattern) == 0) { // k not starting with pattern
    clone[k] = v;
  }
});

Solution 2 - Using Pure ECMAScript and Creating a New Object

var clone = {};

for (var k in map) {
  if (map.hasOwnProperty(k) && (k.indexOf(pattern) == 0)) {
    clone[k] = map[k];
  }
}

Solution 3 - Using Pure ECMAScript and Using the Source Object

for (var k in map) {
  if (map.hasOwnProperty(k) && (k.indexOf(pattern) == 0)) {
    delete map[k];
  }
}

Or, in modern browsers:

Object.keys(map).forEach(function (k) {
  if (k.indexOf(pattern) == 0) {
    delete map[k];
  }
});

Update - Using Regular Expressions for the Pattern Match

Instead of using the following to match if the key k starts with a letter with:

k[0] == letter // to match or letter

or to match if the key k starts with a string with:

k.indexOf(pattern) // to match a string

you can use instead this regular expression:

new Regexp('^' + pattern).test(k)
// or if the pattern isn't variable, for instance you want
// to match 'X', directly use:
//   /^X/.test(k)
haylem
  • 22,460
  • 3
  • 67
  • 96
  • Thanks is it possible through regular expression, have edited my question. – newbie Sep 03 '13 at 19:15
  • @newbie: no, it's not. Or at least not in the way you mean in the question. But you could do the `startsWith` with a regular expression. I'll update my answer. – haylem Sep 03 '13 at 19:16
  • You are using k[0] , Will it work if letter starts with 'Xke" instead of only 'X' – newbie Sep 03 '13 at 19:33
  • @newbie: note that I don't recommend using k[0] to check for the first letter. That's from David's original answer. I recommended from the start to use `k.indexOf(pattern) == 0`, where pattern could be `"Xke"` or any string. It's more generic (and also possibly slow for a very very very long key, but that's unlikely. – haylem Sep 03 '13 at 19:35
  • @newbie: also, while you can use regular expressions, I honestly don't know why you would in that case. I wouldn't recommend using this approach either. – haylem Sep 03 '13 at 19:36