从Javascript地图中移除特定元素

19
如何从以下地图中删除所有键值对,其中键以X开头
var map = new Object(); 
map[XKey1] = "Value1";
map[XKey2] = "Value2";
map[YKey3] = "Value3";
map[YKey4] = "Value4";

编辑

有没有办法通过正则表达式,可能使用 ^。比如map[^XKe],其中关键字以“Xke”开头而不是“X”


1
使用 for...in 循环结合 delete 关键字进行删除。 - Blazemonger
@Blazemonger 我认为他们的意图是循环遍历数组 map,如果键以 "x" 开头,则删除该元素。 - user1477388
@user1477388:那么他、她或他们需要解释和澄清,而不是依靠猜测。 - David Thomas
@DavidThomas 对我来说非常清楚,但是...你下面的回答很好,干得好! - user1477388
1
XKey1是一个具有不同值的变量吗?还是应该像map["XKey1"] = "Value1";那样用引号括起来? - Joe Enos
显示剩余2条评论
4个回答

18

您可以使用Object.key来迭代地遍历map键。

最简单的解决方案是:

此处演示

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

所以这里有一个另一种版本的removeKeyStartsWith,使用了你说的正则表达式:

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);

使用正则表达式的解决方案可以满足您的需求,即使您使用了letter=Xke,但是如果选择不使用正则表达式的另一种解决方案,则需要将Key[0]==letter替换为key.substr(0,3)==letter

谢谢。通过正则表达式是否可能实现?我已经编辑了我的问题。 - newbie
key[0]==letter,如果我的key以'XKe'开头而不是X,会怎么样? - newbie
如果你使用XKe作为字母或者使用key.substr(0,3)==letter代替key[0]==letter,那么使用正则表达式的新手解决方案将会起作用。 - Charaf JRA
谢谢。请不要介意,我应该如何在Jsfiddle中进行测试?我选择了所有内容,然后点击了“运行”。 - newbie
@新手 使用您的浏览器控制台,您将在那里看到结果。 - Charaf JRA

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

JS Fiddle演示。顺便说一句,通常使用对象字面量比构造函数更容易(并且被认为是“最佳实践”),因此以下内容值得展示(即使你喜欢new Object()语法):

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

JS Fiddle演示

如果你真的想使用正则表达式(但为什么呢?),那么以下内容可以实现:

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演示

最后(至少现在)一个扩展了Object原型的方法,允许用户搜索以给定字符串开头、以给定字符串结尾或(通过同时使用startsWithendsWith)是一个给定字符串的属性(大小写敏感或不敏感):

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演示

参考资料:


谢谢。通过正则表达式是否可能实现?我已经编辑了我的问题。 - newbie
那么你将需要使用 substr。 - Charaf JRA
@新手:不,按照原文的方式是行不通的,但你可以使用prop.indexOf(letter) === 0。然而,虽然我还没有添加该选项,但我已经发布了一个解决方案,应该能够满足您目前的需求(就我目前的理解而言),它扩展了“Object”原型。我很快会添加参考和解释(先去做几个家务活,抱歉!XD)。 - David Thomas
1
+1:很好的回答。我觉得opts/settings方法有点过于复杂和混乱,而且更愿意采用多种方法(或者传递一个正则表达式进行匹配),但是...无法否认你为编写一个好的答案所付出的努力! - haylem
@haylem:谢谢!我基本上同意你的看法;但是最后一次迭代的“厨房水槽”风格部分是为了尝试预测更多的请求(另外我也很喜欢让事情易于扩展,我认为这种方法是可行的)。=) - David Thomas

3
你可以轻松地通过以下方式获得它。
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);

这是一种简单的方法来移除它。


1

前提条件

假设您的原始输入为:

var map = new Object();

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

假设有一个变量pattern,其中包含您想要筛选的键(例如"X""Y""prefixSomething"等)。

解决方案1 - 使用jQuery进行过滤并创建新对象

var clone = {};

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

方案二 - 使用纯ECMAScript创建新对象

var clone = {};

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

解决方案3 - 使用纯ECMAScript并使用源对象

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

或者,在现代浏览器中:

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

更新 - 使用正则表达式进行模式匹配

不再使用以下代码来匹配键 k 是否以字母开头:

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

或者匹配,如果键k以字符串开头:

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

你可以使用这个正则表达式代替:


new Regexp('^' + pattern).test(k)
// or if the pattern isn't variable, for instance you want
// to match 'X', directly use:
//   /^X/.test(k)

谢谢。通过正则表达式实现是否可能,我已经编辑了我的问题。 - newbie
@新手:不,它不是。或者至少不是你在问题中的意思。但是你可以使用正则表达式来执行startsWith。我会更新我的答案。 - haylem
你正在使用 k[0],如果字母以“Xke”开头而不仅仅是“X”,它会起作用吗? - newbie
@新手:请注意,我不建议使用k[0]来检查第一个字母。这是来自David原始答案的。我一开始就推荐使用k.indexOf(pattern) == 0,其中pattern可以是“Xke”或任何字符串。它更通用(对于非常非常长的密钥也可能很慢,但这不太可能)。 - haylem
@新手:另外,虽然你可以使用正则表达式,但我真的不知道为什么你会在这种情况下使用它。我也不建议使用这种方法。 - haylem

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接