2011-07-19 15 views
9

Tengo un objeto con las teclas con nombre:¿Cómo puedo obtener claves de objeto por un patrón?

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

¿Hay una manera de conseguir todas las llaves por un patrón, por ejemplo. todas las llaves tienen a Peter en ella?

El caso es que yo quiero tener todas las claves filtrados en un array por ejemplo:

var filteredNames: [ 
    "Peter Pan", 
    "Peter Parker", 
    ... 
] 

Respuesta

13

Puede hacerlo fácilmente haciendo un bucle de llaves a sí mismo:

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 
+4

+1 para usar * hasOwnProperty *. Si se requiere una coincidencia exacta de texto sin formato, no se necesita una expresión regular (la cadena se convertirá a RegExp por * coincidencia *). Si se usa una epxression regular, * test * es más adecuada ya que es un algoritmo más simple y devuelve un booleano (por ejemplo, 'filter.test (key)'), mientras que * match * devuelve una matriz que se convertirá en boolean. – RobG

3

Si quieres que entre mayúsculas y minúsculas:

var filteredNames = []; 

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

Si no es así:

var filteredNames = []; 

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

También necesitará usar hasOwnProperty() en for for, de lo contrario, es posible que tenga claves seleccionadas de más arriba en la cadena del prototipo (a menos que eso sea lo que desea, por supuesto). – Lepidosteus

+0

@Lepidosteus: Excepto que es un objeto literal, por lo que no habrá ninguna propiedad enumerable en la cadena a menos que extienda 'Object.prototype', en cuyo caso su código * debe romperse * para que pueda corregir ese error. – user113716

+0

Tiene toda la razón, pero estaba pensando más en la línea de su código como un ejemplo, mientras que su caso de uso real podría ser algo donde los nombres tienen propiedades de prototipo. Después de haber visto tantos abusos de código de producción, tiendo a levantar el escudo antes de ser golpeado, por así decirlo. – Lepidosteus

1

Puede extender el prototipo de Array de JavaScript, así:

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

Ahora, en realidad, no he probado este código, pero esto daría a todas las matrices que cree en JavaScript un método .regex_search que toma un argumento 'patrón'. Esto devolverá falso cuando no se encuentren coincidencias o una matriz de índices cuando los elementos coincidan.

Podría iterar sobre esta matriz y tomar esos índices de la matriz original.

+0

Está iterando sobre las claves de un objeto, no sobre una matriz. Además, no recomendaría editar la cadena prototipo de objetos nativos como Array. – Lepidosteus

+0

Tiene toda la razón, debo haberlo leído :-) – ikanobori

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

Si este código se está ejecutando en un navegador, tenga en cuenta que 'forEach' y' filter' no son compatibles en IE8 y versiones anteriores. – user113716

0

ECMAScript 5.1 proporciona Object.keys() para devolver los nombres de las propiedades de un objeto.

var obj = { 0: 'a', 1: 'b', 2: 'c' }; 
console.log(Object.keys(obj)); // console: ['0', '1', '2'] 

Source.

Standard.

Cuestiones relacionadas