Creación dinámica de claves en una matriz asociativa de JavaScript

199

¿Cómo puedo crear claves dinámicamente en matrices asociativas de JavaScript?

Toda la documentación que he encontrado hasta ahora es para actualizar las claves que ya están creadas:

 arr['key'] = val;

Tengo una cuerda como esta " name = oscar "

Y quiero terminar con algo como esto:

{ name: 'whatever' }

Es decir, dividí la cadena y obtuve el primer elemento, y quiero poner eso en un diccionario.

Código

var text = ' name = oscar '
var dict = new Array();
var keyValuePair = text.split(' = ');
dict[ keyValuePair[0] ] = 'whatever';
alert( dict ); // prints nothing.
OscarRyz
fuente
24
Saltar enlace a la respuesta de Eugene por conveniencia
user56reinstatemonica8

Respuestas:

143

Usa el primer ejemplo. Si la clave no existe, se agregará.

var a = new Array();
a['name'] = 'oscar';
alert(a['name']);

Aparecerá un cuadro de mensaje que contiene 'oscar'.

Tratar:

var text = 'name = oscar'
var dict = new Array()
var keyValuePair = text.replace(/ /g,'').split('=');
dict[ keyValuePair[0] ] = keyValuePair[1];
alert( dict[keyValuePair[0]] );
tvanfosson
fuente
Lo ejecuté como muestra en Firefox solo para estar seguro. ¿Te aseguraste de poner 'nombre' entre comillas?
tvanfosson
1
Uhmm no, porque estoy creando la clave "dinámicamente", no estáticamente. Déjame verificar dos veces :)
OscarRyz
2
Consulte la explicación más completa de Danny. No podrá hacer referencia a los valores de la matriz en un bucle for con un índice (como myarray [i]). Espero que no sea demasiado confuso.
MK_Dev
44
Aún mejor es usar un objeto (notación de paréntesis {}) para evitar la sobrecarga de tener .length, .slice (), etc., que están incluidos en el prototipo de matriz
bjornl
488

De alguna manera, todos los ejemplos, aunque funcionan bien, son demasiado complicados:

  • Utilizan new Array(), que es una exageración (y una sobrecarga) para una matriz asociativa simple (diccionario AKA).
  • Los mejores usan new Object(). Funciona bien, pero ¿por qué toda esta escritura adicional?

Esta pregunta está etiquetada como "principiante", así que hagámoslo simple.

La forma súper simple de usar un diccionario en JavaScript o "¿Por qué JavaScript no tiene un objeto de diccionario especial?":

// create an empty associative array (in JavaScript it is called ... Object)
var dict = {};   // huh? {} is a shortcut for "new Object()"

// add a key named fred with value 42
dict.fred = 42;  // we can do that because "fred" is a constant
                 // and conforms to id rules

// add a key named 2bob2 with value "twins!"
dict["2bob2"] = "twins!";  // we use the subscript notation because
                           // the key is arbitrary (not id)

// add an arbitrary dynamic key with a dynamic value
var key = ..., // insanely complex calculations for the key
    val = ...; // insanely complex calculations for the value
dict[key] = val;

// read value of "fred"
val = dict.fred;

// read value of 2bob2
val = dict["2bob2"];

// read value of our cool secret key
val = dict[key];

Ahora cambiemos los valores:

// change the value of fred
dict.fred = "astra";
// the assignment creates and/or replaces key-value pairs

// change value of 2bob2
dict["2bob2"] = [1, 2, 3];  // any legal value can be used

// change value of our secret key
dict[key] = undefined;
// contrary to popular beliefs assigning "undefined" does not remove the key

// go over all keys and values in our dictionary
for (key in dict) {
  // for-in loop goes over all properties including inherited properties
  // let's use only our own properties
  if (dict.hasOwnProperty(key)) {
    console.log("key = " + key + ", value = " + dict[key]);
  }
}

Eliminar valores también es fácil:

// let's delete fred
delete dict.fred;
// fred is removed, the rest is still intact

// let's delete 2bob2
delete dict["2bob2"];

// let's delete our secret key
delete dict[key];

// now dict is empty

// let's replace it, recreating all original data
dict = {
  fred:    42,
  "2bob2": "twins!"
  // we can't add the original secret key because it was dynamic,
  // we can only add static keys
  // ...
  // oh well
  temp1:   val
};
// let's rename temp1 into our secret key:
if (key != "temp1") {
  dict[key] = dict.temp1; // copy the value
  delete dict.temp1;      // kill the old key
} else {
  // do nothing, we are good ;-)
}
Eugene Lazutkin
fuente
2
Hola, sé que estoy respondiendo a la respuesta anterior, pero ocupa un lugar destacado en Google, por lo que preguntaré de todos modos. Estoy un poco confundido acerca de lo que significa "no podemos agregar la clave secreta original porque era dinámica, solo podemos agregar claves estáticas" en su ejemplo.
Karel Bílek
1
Significa precisamente lo que dice: no sabemos su valor, por lo que no podemos representarlo como una constante, lo cual es necesario al especificar una clave en un objeto literal.
Eugene Lazutkin
3
Sin embargo, "no podemos agregar la clave secreta original porque era dinámica" no es correcta por sí misma, a pesar de que no puede usar una variable como clave directamente en {}, o como una clave con notación de punto. Todavía podemos agregar una clave dinámica a través de "dict [key] = val", como se muestra al principio del ejemplo. La limitación está en usar la notación {}, en lugar de la clave en sí.
Zut
8
Esto parece la respuesta de Sheldon Cooper :)
jpatiaga
44
respuesta completa perfecta, debería ser la predeterminada
Dennis Golomazov
29

Javascript no tiene matrices asociativas , tiene objetos .

Las siguientes líneas de código hacen exactamente lo mismo: establecer el campo 'nombre' en un objeto en 'orion'.

var f = new Object(); f.name = 'orion';
var f = new Object(); f['name'] = 'orion';
var f = new Array(); f.name = 'orion';
var f = new Array(); f['name'] = 'orion';
var f = new XMLHttpRequest(); f['name'] = 'orion';

Parece que tiene una matriz asociativa porque una Arraytambién es una Object; sin embargo, en realidad no está agregando cosas a la matriz, está configurando campos en el objeto.

Ahora que eso está aclarado, aquí hay una solución funcional a su ejemplo.

var text = '{ name = oscar }'
var dict = new Object();

// Remove {} and spaces
var cleaned = text.replace(/[{} ]/g, '');

// split into key and value
var kvp = cleaned.split('=');

// put in the object
dict[ kvp[0] ] = kvp[1];
alert( dict.name ); // prints oscar.
Orion Edwards
fuente
Suponiendo que la cadena de texto en realidad tiene las llaves, se puede más o menos lo tratan como JSON .. reemplazar el signo = con un: y tienes un objeto a eval ..
neonski
1
Vaya, la cadena no está delimitada correctamente. Nada de expresiones regulares no puede arreglar.
neonski
9

En respuesta a MK_Dev, uno puede iterar, pero no consecutivamente.(Para eso obviamente se necesita una matriz)

La búsqueda rápida de google aparece tablas hash en javascript

Código de ejemplo para recorrer valores en un hash (del enlace mencionado anteriormente):

var myArray = new Array();
myArray['one'] = 1;
myArray['two'] = 2;
myArray['three'] = 3;

// show the values stored
for (var i in myArray) {
    alert('key is: ' + i + ', value is: ' + myArray[i]);
}
Danny
fuente
5

Código original (agregué los números de línea para poder consultarlos):

1  var text = ' name = oscar '
2  var dict = new Array();
3  var keyValuePair = text.split(' = ');
4  dict[ keyValuePair[0] ] = 'whatever';
5  alert( dict ); // prints nothing.

Casi ahí...

  • línea 1: deberías hacer un trimtexto en modo así name = oscar.
  • línea 3: está bien siempre y cuando SIEMPRE tenga espacios alrededor de su igual. podría ser mejor no estar trimen la línea 1, usar =y recortar cada keyValuePair
  • agregue una línea después de 3 y antes de 4:

    key = keyValuePair[0];`
  • línea 4: ahora se convierte en:

    dict[key] = keyValuePair[1];
  • línea 5: Cambiar a:

    alert( dict['name'] );  // it will print out 'oscar'

Lo que intento decir es que dict[keyValuePair[0]]no funciona, debe establecer una cadena keyValuePair[0]y usarla como clave asociativa. Esa es la única forma en que conseguí que el mío funcionara. Después de configurarlo, puede consultarlo con índice numérico o ingresar comillas.

Espero que ayude.

Andrea
fuente
4

Todos los navegadores modernos admiten un mapa , que es una restricción de datos clave / valor. Hay un par de razones que hacen que usar un Mapa sea mejor que un Objeto:

  • Un objeto tiene un prototipo, por lo que hay claves predeterminadas en el mapa.
  • Las claves de un objeto son cadenas, donde pueden ser cualquier valor para un mapa.
  • Puede obtener el tamaño de un Mapa fácilmente mientras tiene que hacer un seguimiento del tamaño de un Objeto.

Ejemplo:

var myMap = new Map();

var keyObj = {},
    keyFunc = function () {},
    keyString = "a string";

myMap.set(keyString, "value associated with 'a string'");
myMap.set(keyObj, "value associated with keyObj");
myMap.set(keyFunc, "value associated with keyFunc");

myMap.size; // 3

myMap.get(keyString);    // "value associated with 'a string'"
myMap.get(keyObj);       // "value associated with keyObj"
myMap.get(keyFunc);      // "value associated with keyFunc"

Si desea que las claves a las que no se hace referencia desde otros objetos se recojan como basura, considere usar un WeakMap en lugar de un Mapa.

Vitalii Fedorenko
fuente
1
var myArray = new Array();
myArray['one'] = 1;
myArray['two'] = 2;
myArray['three'] = 3;
// show the values stored
for (var i in myArray) {
    alert('key is: ' + i + ', value is: ' + myArray[i]);
}

esto está bien pero itera a través de cada propiedad del objeto de matriz. si solo desea recorrer las propiedades myArray.one, myArray.two ... intente así

myArray['one'] = 1;
myArray['two'] = 2;
myArray['three'] = 3;
myArray.push("one");
myArray.push("two");
myArray.push("three");
for(i=0;i<maArray.length;i++{
    console.log(myArray[myArray[i]])
}

ahora puede acceder a ambos mediante myArray ["one"] e iterar solo a través de estas propiedades.

Sasinda Rukshan
fuente
¿Ha contado el recuento de tipos erróneos en su ejemplo? :-) maArray, olvidado cerrado ')' ...
Brian Haak
Gracias por el ejemplo ¡Podríamos unirnos Arrayy Objecttrabajar solo con Objectárboles! Maravillosa visión! ¡Es muy útil hacer Object.getOwnPropertyNames(obj/array)!
Brian Haak
1
var obj = {};

                for (i = 0; i < data.length; i++) {
                    if(i%2==0) {
                        var left = data[i].substring(data[i].indexOf('.') + 1);
                        var right = data[i + 1].substring(data[i + 1].indexOf('.') + 1);

                        obj[left] = right;
                        count++;
                    }
                }
                console.log("obj");
                console.log(obj);
                // show the values stored
                for (var i in obj) {
                    console.log('key is: ' + i + ', value is: ' + obj[i]);
                }

            }
        };

}

usuario2266928
fuente