2010-03-24 20 views
65

I tienen una matriz creada con este código:¿Cómo obtener claves de matriz en Javascript?

var widthRange = new Array(); 
widthRange[46] = { min:0, max:52 }; 
widthRange[66] = { min:52, max:70 }; 
widthRange[90] = { min:70, max:94 }; 

quiero conseguir cada uno de los valores 46, 66, 90 en un bucle. Intenté for (var key in widthRange), pero esto me da un montón de propiedades adicionales (supongo que son funciones del objeto). No puedo usar un ciclo for para regular ya que los valores no son secuenciales.

+8

Parece que tiene datos que, si bien tienen teclas numéricas, en realidad no son datos de matriz. Me gustaría ver el uso de un objeto regular aquí. – Quentin

Respuesta

87

Es necesario llamar a la función hasOwnProperty compruebe si la propiedad está realmente definida en el objeto mismo (en oposición a su prototipo), así:

for (var key in widthRange) { 
    if (key === 'length' || !widthRange.hasOwnProperty(key)) continue; 
    var value = widthRange[key]; 
} 

Tenga en cuenta que necesita un cheque por separado para length.
Sin embargo, no debería usar una matriz aquí; deberías usar un objeto regular Todos los objetos Javascript funcionan como matrices asociativas.

Por ejemplo:

var widthRange = { }; //Or new Object() 
widthRange[46] = { sel:46, min:0, max:52 }; 
widthRange[66] = { sel:66, min:52, max:70 }; 
widthRange[90] = { sel:90, min:70, max:94 }; 
+2

¿En serio? Wow, aprendo algo todos los días aquí, y muchas veces es de ti. SLaks :-) Me sorprende que Array haga un seguimiento de sus índices explícitamente establecidos de esa manera. Quizás no debería ser. – Pointy

+0

@SLaks: Gracias, cambiarlo a un objeto parece ser la mejor solución. Una pregunta más: ¿hay alguna manera de iterar en orden inverso? – DisgruntledGoat

+0

No; tendrás que hacerlo tú mismo. – SLaks

3
for (var i = 0; i < widthRange.length; ++i) { 
    if (widthRange[i] != null) { 
    // do something 
    } 
} 

Realmente no se puede obtener sólo las teclas que ha establecido porque no es así como funciona una matriz. Una vez que estableces el elemento 46, también tienes 0 a 45 establecidos también (aunque son nulos).

Siempre se puede tiene dos matrices:

var widthRange = [], widths = [], newVal = function(n) { 
    widths.push(n); 
    return n; 
}; 
widthRange[newVal(26)] = { whatever: "hello there" }; 

for (var i = 0; i < widths.length; ++i) { 
    doSomething(widthRange[widths[i]]); 
} 

edición bien puede ser que estoy todo mojado aquí ...

+0

Las matrices solo hacen un seguimiento de la longitud, no pasan y crean la cantidad de objetos. Básicamente, cuando se encuentra un nuevo índice, comprueba si ese nuevo índice es mayor que la longitud ... si es que el nuevo índice se convierte en la nueva longitud. Por eso, solo es posible obtener los índices que definió con un bucle for-in – Bob

1

Su original ejemplo funciona bien para mí:

<html> 
<head> 
</head> 
<body> 
<script> 
var widthRange = new Array(); 
widthRange[46] = { sel:46, min:0, max:52 }; 
widthRange[66] = { sel:66, min:52, max:70 }; 
widthRange[90] = { sel:90, min:70, max:94 }; 

var i = 1; 
for (var key in widthRange) 
{ 
    document.write("Key #" + i + " = " + key + "; &nbsp;&nbsp;&nbsp; min/max = " + widthRange[key].min + "/" + widthRange[key].max + "<br />"); 
    i++; 
} 
</script> 
</html> 

Resultados en el navegador (Firefox 3.6.2 en Windows XP):

Key #1 = 46;  min/max = 0/52 
Key #2 = 66;  min/max = 52/70 
Key #3 = 90;  min/max = 70/94 
+2

Apuesto a que está importando prototipos o algo así. En general, esos bucles "en" son riesgosos. – Pointy

+0

Bueno, estoy usando jQuery pero también Joomla que usa mootools, algo está agregando esas propiedades. – DisgruntledGoat

0

Parece que funciona.

var widthRange = new Array(); 
widthRange[46] = { sel:46, min:0, max:52 }; 
widthRange[66] = { sel:66, min:52, max:70 }; 
widthRange[90] = { sel:90, min:70, max:94 }; 

for (var key in widthRange) 
{ 
    document.write(widthRange[key].sel + "<br />"); 
    document.write(widthRange[key].min + "<br />"); 
    document.write(widthRange[key].max + "<br />"); 
} 
1

creo que se debe utilizar un objeto ({}) y no una matriz ([]) para esto.

Un conjunto de datos está asociado a cada tecla. Grita por usar un objeto. No:

var obj = {}; 
obj[46] = { sel:46, min:0, max:52 }; 
obj[666] = { whatever:true }; 

// This is what for..in is for 
for (var prop in obj) { 
    console.log(obj[prop]); 
} 

Tal vez un poco de materia utilidad como esto puede ayudar:

window.WidthRange = (function() { 
    var obj = {}; 
    return { 
    getObj: function() {return obj;} 
    , add: function (key, data) { 
     obj[key] = data; 
     return this; // enabling chaining 
     } 
    } 
})(); 

// Usage (using chaining calls): 
WidthRange.add(66, {foo: true}) 
.add(67, {bar: false}) 
.add(69, {baz: 'maybe', bork:'absolutely'}); 

var obj = WidthRange.getObj(); 
for (var prop in obj) { 
    console.log(obj[prop]); 
} 
18

Si usted está haciendo cualquier tipo de manipulación de matrices/o inspección colección Le recomiendo usar Underscore.js. Es pequeño, bien probado y le ahorrará días/semanas/años de jaqueca de dolor de cabeza. Aquí es su función claves:

Claves

recuperar todos los nombres de las propiedades del objeto.

_.keys({one : 1, two : 2, three : 3}); 
=> ["one", "two", "three"] 
0

escribí una función de lo que funciona bien con todas las instancias de objetos (arrays son aquellos).

Object.prototype.toArray = function() 
{ 
    if(!this) 
    { 
     return null; 
    } 

    var c = []; 

    for (var key in this) 
    { 
     if ((this instanceof Array && this.constructor === Array && key === 'length') || !this.hasOwnProperty(key)) 
     { 
      continue; 
     } 

     c.push(this[key]); 
    } 

    return c; 
}; 

Uso:

var a = [ 1, 2, 3 ]; 
a[11] = 4; 
a["js"] = 5; 

console.log(a.toArray()); 

var b = { one: 1, two: 2, three: 3, f: function() { return 4; }, five: 5 }; 
b[7] = 7; 

console.log(b.toArray()); 

Salida:

> [ 1, 2, 3, 4, 5 ] 
> [ 7, 1, 2, 3, function() { return 4; }, 5 ] 

Puede ser útil para cualquier persona.

+2

Extender un prototipo que no creó es una muy mala idea, sin importar cuán conveniente piense que es. – doug65536

54

Las claves codificadas se pueden consultar con Object.keys(array).

+2

gracias, justo lo que necesitaba. – spazm

+0

Esto devuelve las claves como cadenas, no como números, para que todos lo sepan. –

0

... ????

Alternativamente, si usted tiene una lista de elementos que desea utilizar ...

var range = [46, 66, 90] 
    , widthRange=[] 
    , write=[]; 

    widthRange[46] = { min:0, max:52 }; 
    widthRange[66] = { min:52, max:70 }; 
    widthRange[90] = { min:70, max:94 }; 

for(var x=0; x<range.length; x++){var key, wr; 

    key = range[x]; 

    wr = widthRange[key] || false; 

    if(wr===false){continue;} 

    write.push(['key: #',key, ', min: ', wr.min, 'max:', wr.max].join('')); 

    } 
2

Digamos que su matriz parecía arr = [ { a: 1, b: 2, c: 3 }, { a: 4, b: 5, c: 6 }, { a: 7, b: 8, c: 9 } ] (o posiblemente otras teclas) que podría hacer

arr.map((o) => { 
    return Object.keys(o) 
}).reduce((prev, curr) => { 
    return prev.concat(curr) 
}).filter((col, i, array) => { 
    return array.indexOf(col) === i 
}); 

["a", "b", "c"]

2
widthRange.map(function(_, i) { return i }); 

o

widthRange.map((_, i) => i); 
Cuestiones relacionadas