20

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'

7
  • 1
    delete with a for...in loop Commented Sep 3, 2013 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. Commented Sep 3, 2013 at 18:38
  • @user1477388: then he, she or they need to explain, and clarify, that rather than depending upon guess-work. Commented Sep 3, 2013 at 18:43
  • @DavidThomas It was perfectly clear to me, but... Your answer below is good, nice work! Commented Sep 3, 2013 at 18:45
  • 1
    Is XKey1 a variable with a different value? Or are those supposed to be in quotes like map["XKey1"] = "Value1";? Commented Sep 3, 2013 at 19:01

4 Answers 4

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

Sign up to request clarification or add additional context in comments.

5 Comments

Thanks is it possible through regular expression, have edited my question.
key[0]==letter, What if my key starts with 'XKe' instead of X
@newbie solution that use regex will work if you use XKe as letter or instead of key[0]==letter use key.substr(0,3)==letter
Thanks.Please never mind, how should i test in Jsfiddle, i selected all and then clicked Run
@newbie use console of your browser , you will see results there
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:

5 Comments

Thanks is it possible through regular expression, have edited my question.
then you will need to user substr
@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).
+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: 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). =)
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.

Comments

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)

5 Comments

Thanks is it possible through regular expression, have edited my question.
@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.
You are using k[0] , Will it work if letter starts with 'Xke" instead of only 'X'
@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.
@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.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.