如何通过模式获取对象键?

25

我有一个具有命名键的对象:

var names = {
  "Peter Pan": {...},
  "Peter Parker": {...},
  "Tony Stark": {...},
  ...
}

有没有一种方法可以通过模式获取所有键,例如所有包含Peter的键?

我的情况是我想在一个数组中拥有所有过滤出来的键,例如:

var filteredNames: [
  "Peter Pan",
  "Peter Parker",
  ...
]
4个回答

30
var filteredNames = Object.keys(names).filter((name) => /Peter/.test(name));

1
如果此代码在浏览器中运行,请注意IE8及以下版本不支持forEachfilter - user113716

26

您可以通过自己循环键来轻松完成:

var filtered_keys = function(obj, filter) {
  var key, keys = [];
  for (key in obj) {
    if (obj.hasOwnProperty(key) && filter.test(key)) {
      keys.push(key);
    }
  }
  return keys;
}
// example:
var filteredNames = filtered_keys(names, /Peter/); // second parameter is a javascript regex object, so for exemple for case insensitive you would do /Peter/i    

ES6

let filtered_keys = (obj, filter) => {
  let key, keys = []
  for (key in obj)
    if (obj.hasOwnProperty(key) && filter.test(key))
      keys.push(key)
  return keys
}

// example:
let filteredNames = filtered_keys(names, /Peter/)

4
使用hasOwnProperty值得点赞。如果需要精确匹配纯文本,就不需要使用正则表达式(字符串将被转换为RegExp通过match)。如果使用正则表达式,则test更适合,因为它是一个更简单的算法,并且返回一个布尔值(例如filter.test(key)),而match返回一个数组,它将被类型转换为布尔值。 - RobG

3
如果您想区分大小写:
var filteredNames = [];

for( name in names ) {
    if( name.indexOf( "Peter" ) > -1 ) {
        filteredNames.push( name );
    }
}

如果不是:
var filteredNames = [];

for( name in names ) {
    if( /peter/gi.test( name ) ) {
        filteredNames.push( name );
    }
}

1
在for in循环中,你还需要使用hasOwnProperty()方法,否则可能会选择来自原型链上层的键(除非这正是你想要的)。 - Lepidosteus
@Lepidosteus:除非你扩展了Object.prototype,否则它只是一个对象字面量,因此在链上不会有任何可枚举的属性,如果你扩展了Object.prototype,那么你的代码应该会出问题,这样你就可以纠正这个缺陷。 - user113716
你说得完全正确,但我更多地考虑到他的代码只是一个示例,而他真正的用例可能涉及名称具有原型属性的情况。在生产代码中看到了这么多对for in的误用,我倾向于在被打击之前就提高警惕。 - Lepidosteus
@Lepidosteus:是的,如果它不是一个对象字面量,而是由一个自定义构造函数和其原型上的可枚举属性所生成的产品,那么如果这些属性应该被排除,那么可能就需要使用 Object.getOwnPropertyNames()。原型可能带有应该被枚举的默认值。 - user113716

0
你可以扩展JavaScript数组原型,像这样:
Array.prototype.regex_search = function(pattern) {
  var returns = [];
  for(var i = 0; i < this.length; i++) {
    if(this[i].match(pattern) {
      returns.push(i);
    }
  }
  if(returns.length) {
    return returns;
  } else {
    return false;
  }
}

现在我还没有实际测试过这段代码,但它将为您在JavaScript中创建的所有数组提供一个方法.regex_search,该方法接受一个参数'pattern'。当没有匹配项时,它将返回false,否则将返回一个索引数组。

然后,您可以遍历此数组并从原始数组中取出这些索引。


他正在迭代一个对象的键,而不是数组。此外,我不建议编辑诸如Array之类的本地对象的原型链。 - Lepidosteus

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