objetos - matriz javascript
javascript array asociativo Y indexado? (10)
Aunque estoy de acuerdo con las respuestas dadas, en realidad puedes lograr lo que dices con getters y setters. Por ejemplo:
var a = [1];
//This makes a["blah"] refer to a[0]
a.__defineGetter__("blah", function(){return this[0]});
//This makes a["blah"] = 5 actually store 5 into a[0]
a.__defineSetter__("blah", function(val){ this[0] = val});
alert(a["blah"]); // emits 1
a["blah"] = 5;
alert(a[0]); // emits 5
¿Es esto lo que estás buscando? Creo que hay una manera más moderna y diferente de hacer getters y setters pero no puedo recordar.
¿puede una matriz en JS ser asociativa e indexada? Me gustaría poder buscar un elemento en la matriz por su posición o un valor clave ... ¿es posible?
Después de leer la definición de Wikipedia de la matriz asociativa , voy a romper con el conocimiento tradicional de JavaScript y decir, "sí, JavaScript tiene matrices asociativas". Con las matrices de JavaScript, puede agregar, reasignar, eliminar y buscar valores por sus claves (y las claves pueden ser cadenas entrecomilladas), que es lo que Wikipedia dice que las matrices asociativas deberían ser capaces de hacer.
Sin embargo, parece que está preguntando algo diferente: si puede buscar el mismo valor por índice o clave. Eso no es un requisito de matrices asociativas (vea el artículo de Wikipedia). Las matrices asociativas no tienen que darle la capacidad de obtener un valor por índice.
Las matrices de JavaScript son muy similares a los objetos de JavaScript.
arr=[];
arr[0]="zero";
arr[1]="one";
arr[2]="two";
arr["fancy"]="what?";
Sí, eso es una matriz, y sí, puede salirse con índices no numéricos. (Si tiene curiosidad, después de todo esto, arr.length es 3.)
En la mayoría de los casos, creo que debes apegarte a los índices numéricos cuando utilizas matrices. Eso es lo que la mayoría de los programadores esperan, creo.
El enlace es a mi publicación en el blog sobre el tema.
El orden en que aparecen los objetos en una matriz javascript asociativa no está definido, y será diferente en las diferentes implementaciones. Por esa razón, no se puede contar realmente con una clave asociativa dada para estar siempre en el mismo índice.
EDITAR:
como señala Perspx, no hay realmente arreglos asociativos verdaderos en javascript. La declaración foo["bar"]
es solo azúcar sintáctica para foo.bar
Si confías en que el navegador mantiene el orden de los elementos en un objeto, puedes escribir una función
function valueForIndex(obj, index) {
var i = 0;
for (var key in obj) {
if (i++ == index)
return obj[key];
}
}
La marea ha cambiado en este. Ahora puedes hacer eso ... ¡y MÁS! Usando Harmony Proxies definitivamente podrías resolver este problema de muchas maneras.
Deberá verificar que sus entornos específicos lo soporten con quizás un poco de ayuda de la corrección de harmony-reflect .
Hay un muy buen ejemplo en la Red de Desarrolladores de Mozilla sobre el uso de un Proxy para encontrar un objeto de elemento de matriz por su propiedad que prácticamente lo resume.
Aquí está mi versión:
var players = new Proxy(
[{
name: ''monkey'',
score: 50
}, {
name: ''giraffe'',
score: 100
}, {
name: ''pelican'',
score: 150
}], {
get: function(obj, prop) {
if (prop in obj) {
// default behavior
return obj[prop];
}
if (typeof prop == ''string'') {
if (prop == ''rank'') {
return obj.sort(function(a, b) {
return a.score > b.score ? -1 : 1;
});
}
if (prop == ''revrank'') {
return obj.sort(function(a, b) {
return a.score < b.score ? -1 : 1;
});
}
var winner;
var score = 0;
for (var i = 0; i < obj.length; i++) {
var player = obj[i];
if (player.name == prop) {
return player;
} else if (player.score > score) {
score = player.score;
winner = player;
}
}
if (prop == ''winner'') {
return winner;
}
return;
}
}
});
console.log(players[0]); // { name: ''monkey'', score: 50 }
console.log(players[''monkey'']); // { name: ''monkey'', score: 50 }
console.log(players[''zebra'']); // undefined
console.log(players.rank); // [ { name: ''pelican'', score: 150 },{ name: ''giraffe'', score: 100 }, { name: ''monkey'', score: 50 } ]
console.log(players.revrank); // [ { name: ''monkey'', score: 50 },{ name: ''giraffe'', score: 100 },{ name: ''pelican'', score: 150 } ]
console.log(players.winner); // { name: ''pelican'', score: 150 }
Los objetos nativos JS solo aceptan cadenas como nombres de propiedad, lo que es cierto incluso para índices de matriz numérica ; las matrices difieren de los objetos normales solo en la medida en que la mayoría de las implementaciones JS almacenarán propiedades indexadas numéricamente de manera diferente (es decir, en una matriz real siempre que sean densas) y su configuración desencadenará operaciones adicionales (por ejemplo, ajuste de la propiedad de length
).
Si está buscando un mapa que acepte claves arbitrarias, tendrá que usar una implementación no nativa . La secuencia de comandos está pensada para una iteración rápida y no de acceso aleatorio por índices numéricos, por lo que podría no ser lo que estás buscando.
Una implementación barebones de un mapa que haría lo que está pidiendo podría verse así:
function Map() {
this.length = 0;
this.store = {};
}
Map.prototype.get = function(key) {
return this.store.hasOwnProperty(key) ?
this.store[key] : undefined;
};
Map.prototype.put = function(key, value, index) {
if(arguments.length < 3) {
if(this.store.hasOwnProperty(key)) {
this.store[key].value = value;
return this;
}
index = this.length;
}
else if(index >>> 0 !== index || index >= 0xffffffff)
throw new Error(''illegal index argument'');
if(index >= this.length)
this.length = index + 1;
this[index] = this.store[key] =
{ index : index, key : key, value : value };
return this;
};
El argumento de index
de put()
es opcional.
Puede acceder a los valores en un mapa map
por clave o índice a través de
map.get(''key'').value
map[2].value
No existen elementos como matrices asociativas en Javascript. Puede usar literales de objeto, que se parecen a matrices asociativas, pero tienen propiedades desordenadas. Los conjuntos de JavaScript normales se basan en índices enteros y no pueden ser asociativos.
Por ejemplo, con este objeto:
var params = {
foo: 1,
bar: 0,
other: 2
};
Puede acceder a propiedades desde el objeto, por ejemplo:
params["foo"];
Y también puede iterar sobre el objeto usando la instrucción for...in
:
for(var v in params) {
//v is equal to the currently iterated property
}
Sin embargo, no existe una regla estricta sobre el orden de iteración de propiedad: dos iteraciones de su literal de objeto podrían devolver las propiedades en diferentes órdenes.
Sí.
test = new Array();
test[0] = ''yellow'';
test[''banana''] = 0;
alert(test[test[''banana'']]);
Vine aquí para querer saber si esto es una mala práctica o no, y en cambio encontré a muchas personas que parecían no entender la pregunta.
Quería tener una estructura de datos que se ordenara pero que pudiera indexarse por clave, para que no requiera iteración en cada búsqueda.
En términos prácticos, esto es bastante simple, pero todavía no he leído nada sobre si es una práctica terrible o no.
var roygbiv = [];
var colour = { key : "red", hex : "#FF0000" };
roygbiv.push(colour);
roygbiv[colour.key] = colour;
...
console.log("Hex colours of the rainbow in order:");
for (var i = 0; i < roygbiv.length; i++) {
console.log(roygbiv[i].key + " is " + roygbiv[i].hex);
}
// input = "red";
console.log("Hex code of input colour:");
console.log(roygbiv[input].hex);
Lo importante es nunca cambiar el valor de matriz [índice] o matriz [clave] directamente una vez que el objeto está configurado o los valores ya no coincidirán. Si la matriz contiene objetos, puede cambiar las propiedades de esos objetos y podrá acceder a las propiedades modificadas por cualquiera de los métodos.
var myArray = Array();
myArray["first"] = "Object1";
myArray["second"] = "Object2";
myArray["third"] = "Object3";
Object.keys(myArray); // returns ["first", "second", "third"]
Object.keys(myArray).length; // returns 3
si quieres el primer elemento, entonces puedes usarlo así:
myArray[Object.keys(myArray)[0]]; // returns "Object1"
var stuff = [];
stuff[0] = "foo";
stuff.bar = stuff[0]; // stuff.bar can be stuff["bar"] if you prefer
var key = "bar";
alert(stuff[0] + ", " + stuff[key]); // shows "foo, foo"