¿Cómo crear un diccionario y agregar pares clave-valor dinámicamente?

324

De la publicación:

Enviar una matriz JSON para recibirla como Diccionario <cadena, cadena>

Estoy tratando de hacer lo mismo que esa publicación. El único problema es que no sé cuáles son las claves y los valores por adelantado. Así que necesito poder agregar dinámicamente los pares clave y valor y no sé cómo hacerlo.

¿Alguien sabe cómo crear ese objeto y agregar pares de valores clave dinámicamente?

He intentado:

var vars = [{key:"key", value:"value"}];
vars[0].key = "newkey";
vars[0].value = "newvalue";

Pero eso no funciona.

KenEucker
fuente
2
Funciona muy bien console.log (vars); muéstrame [clave del objeto: valor "nueva clave" : proto "nuevovalor" : objeto]
Alex Pliutau
Excepto porque es una lista, no un diccionario: \ Creo que los datos también se representan mejor como una lista de "pares" list = [["key1","value1"],["key2","value2"]]. Algunos otros idiomas tienen un tipo de "par" o "tupla". tldr para dict real agregando:dict['key'] = "value"
Jordan Stewart

Respuestas:

553
var dict = []; // create an empty array

dict.push({
    key:   "keyName",
    value: "the value"
});
// repeat this last part as needed to add more key/value pairs

Básicamente, está creando un objeto literal con 2 propiedades (llamado keyy value) e insertándolo (usando push()) en la matriz.


Editar: Entonces, casi 5 años después, esta respuesta está recibiendo votos negativos porque no está creando un literal de objeto JS "normal" (también conocido como map, aka hash, aka dictionary).
Sin embargo, está creando la estructura que OP solicitó (y que se ilustra en la otra pregunta vinculada a), que es una matriz de literales de objetos , cada uno con keyy valuepropiedades. No me pregunten por qué se requería esa estructura, pero es la que se solicitó.

Pero, pero, si lo que desea en un objeto JS simple, y no la estructura solicitada por OP, vea la respuesta de tcll , aunque la notación de corchetes es un poco engorrosa si solo tiene claves simples que son nombres válidos de JS. Puedes hacer esto:

// object literal with properties
var dict = {
  key1: "value1",
  key2: "value2"
  // etc.
};

O utilice la notación de puntos regular para establecer propiedades después de crear un objeto:

// empty object literal with properties added afterward
var dict = {};
dict.key1 = "value1";
dict.key2 = "value2";
// etc.

Usted no quiere que la notación de corchetes si tiene teclas que tienen espacios en ellos, caracteres especiales, o cosas por el estilo. P.ej:

var dict = {};

// this obviously won't work
dict.some invalid key (for multiple reasons) = "value1";

// but this will
dict["some invalid key (for multiple reasons)"] = "value1";

También desea la notación de corchetes si sus claves son dinámicas:

dict[firstName + " " + lastName] = "some value";

Tenga en cuenta que las claves (nombres de propiedades) son siempre cadenas, y los valores que no son cadenas se convertirán en una cadena cuando se usen como clave. Por ejemplo, un Dateobjeto se convierte en su representación de cadena:

dict[new Date] = "today's value";

console.log(dict);
// => {
//      "Sat Nov 04 2016 16:15:31 GMT-0700 (PDT)": "today's value"
//    }

Sin embargo, tenga en cuenta que esto no necesariamente "solo funciona", ya que muchos objetos tendrán una representación de cadena como la "[object Object]"que no constituye una clave no única. Así que ten cuidado con algo como:

var objA = { a: 23 },
    objB = { b: 42 };

dict[objA] = "value for objA";
dict[objB] = "value for objB";

console.log(dict);
// => { "[object Object]": "value for objB" }

A pesar objAy objBser completamente diferentes y únicos elementos, los dos tienen la misma representación básica cadena: "[object Object]".

La razón Dateno se comporta así es que el Dateprototipo tiene un toStringmétodo personalizado que anula la representación de cadena predeterminada. Y tu puedes hacer lo mismo:

// a simple constructor with a toString prototypal method
function Foo() {
  this.myRandomNumber = Math.random() * 1000 | 0;
}

Foo.prototype.toString = function () {
  return "Foo instance #" + this.myRandomNumber;
};

dict[new Foo] = "some value";

console.log(dict);
// => {
//      "Foo instance #712": "some value"
//    }

(Tenga en cuenta que dado que lo anterior usa un número aleatorio , las colisiones de nombres aún pueden ocurrir muy fácilmente. Es solo para ilustrar una implementación de toString).

Entonces, cuando intente usar objetos como claves, JS usará la propia toStringimplementación del objeto , si la hay, o usará la representación de cadena predeterminada.

Flambino
fuente
2
¿Eso es asociativo?
Csaba Toth
1
@CsabaToth No, dictno es un diccionario asociativo. Es una matriz de objetos, cada uno de los cuales es un poco como un diccionario con dos claves: "clave" y "valor".
Roman Starkov
1
Lo que tienes allí es una matriz que simplemente se llama 'dict'.
Jan Kyu Peblik
2
Agradezco la actualización y el seguimiento de información adicional.
Jacob
411
var dict = {};

dict['key'] = "testing";

console.log(dict);

funciona igual que python :)

salida de consola:

Object {key: "testing"} 
Tcll
fuente
3
Este es sin duda el mejor enfoque para crear un diccionario, ¡y ES la respuesta correcta!
Roman
3
Muy importante para inicializar con paréntesis en {}lugar de paréntesis
Jaider
También uso objetos básicos como diccionarios como este. ¡Me alegra ver que esa es la forma correcta!
TKoL
55
'Belleza' de javascript! El objeto ES realmente un diccionario de pares de valores clave en sí mismo
100r
1
@Azurespot, la clave puede ser cualquier cosa que se pueda cambiar, las claves se ordenan por hash después de todo, lo que en python3 difiere en cada ejecución.
Tcll
53

Es tan simple como:

var blah = {}; // make a new dictionary (empty)

o

var blah = {key: value, key2: value2}; // make a new dictionary with two pairs 

luego

blah.key3 = value3; // add a new key/value pair
blah.key2; // returns value2
blah['key2']; // also returns value2
Simon Sarris
fuente
1
@KenEucker Creo que es útil tener respuestas incorrectas en preguntas como esta. Especialmente si alguien explica por qué está equivocado, es un buen recurso de aprendizaje.
CJBrew
32

Como ha declarado que desea un objeto de diccionario (y no una matriz como supongo que algunos lo entienden), creo que esto es lo que busca:

var input = [{key:"key1", value:"value1"},{key:"key2", value:"value2"}];

var result = {};

for(var i = 0; i < input.length; i++)
{
    result[input[i].key] = input[i].value;
}

console.log(result); // Just for testing
Maestro Zen
fuente
La otra solución que usa .push en una matriz funciona para mis usos, pero supongo que esto también funcionaría si lo intentara.
KenEucker
2
A menos que no entienda lo que es un objeto Diccionario, su pregunta es engañosa entonces. ¿Cómo recuperarías un valor por clave de tu matriz?
ZenMaster
Estoy usando JSON.stringify en este objeto y luego lo atrapo con un controlador en MVC 3. Esto es solo para que esté formateado correctamente antes de encadenarlo y enviarlo.
KenEucker
23

JavaScript Object es en sí mismo como un diccionario. No hay necesidad de reinventar la rueda.

var dict = {};

// Adding key-value -pairs
dict['key'] = 'value'; // Through indexer
dict.anotherKey = 'anotherValue'; // Through assignment

// Looping through
for (var item in dict) {
  console.log('key:' + item + ' value:' + dict[item]);
  // Output
  // key:key value:value
  // key:anotherKey value:anotherValue
}

// Non existent key
console.log(dict.notExist); // undefined

// Contains key?
if (dict.hasOwnProperty('key')) {
  // Remove item
  delete dict.key;
}

// Looping through
for (var item in dict) {
  console.log('key:' + item + ' value:' + dict[item]);
  // Output
  // key:anotherKey value:anotherValue
}

Violín

Jani Hyytiäinen
fuente
11

Puedes usar mapas Mapcomo este:

var sayings = new Map();
sayings.set('dog', 'woof');
sayings.set('cat', 'meow');
Preetham Kumar P
fuente
9

Me encontré con esta pregunta en busca de algo similar. Me dio suficiente información para ejecutar una prueba y obtener la respuesta que quería. Por lo tanto, si alguien más quiere saber cómo agregar o buscar dinámicamente un par {clave: 'valor'} en un objeto JavaScript, esta prueba debería decirle todo lo que necesita saber.

var dictionary = {initialkey: 'initialValue'};
var key = 'something';
var key2 =  'somethingElse';
var value = 'value1';
var value2 = 'value2';
var keyInitial = 'initialkey';

console.log(dictionary[keyInitial]);

dictionary[key] =value;
dictionary[key2] = value2;
console.log(dictionary);

salida

initialValue
{ initialkey: 'initialValue',
  something: 'value1',
  somethingElse: 'value2' }
usuario2301449
fuente
2
Esto no es una pregunta. Lo que debe hacer en su lugar es hacer la pregunta y luego responderla usted mismo. Eso sería mucho más fácil de entender y organizar.
SalmonKiller
1
gracias @SalmonKiller no estaba seguro de la terminología adecuada para escribir mi propia pregunta y esperaba que se entendiera, pero luego me encontré con esto en mi búsqueda, toda la información estaba allí pero se extendió entre varias respuestas, así que respondí el concepto de esta pregunta en un de esa manera respondería a alguien que tropezó con esta pregunta buscando lo mismo que yo
usuario2301449
1
Jajaja Estaba revisando esto y parecía una pregunta en lugar de una respuesta. ¡Lo siento!
SalmonKiller
Gracias por agregar esto. También podría ponerlo en un violín como la respuesta anterior.
KenEucker
8
var dictionary = {};//create new object
dictionary["key1"] = value1;//set key1
var key1 = dictionary["key1"];//get key1
SharpCoder
fuente
para un mayor rendimiento, debe hacer referencia en key1 = dictionary.key1lugar de indexarkey1 = dictionary["key1"]
Tcll
4

Puede crear un Diccionario de clase para poder interactuar fácilmente con la lista Diccionario:

class Dictionary {
  constructor() {
    this.items = {};
  }
  has(key) {
    return key in this.items;
  }
  set(key,value) {
    this.items[key] = value;
  }
  delete(key) {
    if( this.has(key) ){
      delete this.items[key]
      return true;
    }
    return false;
  }
}

var d = new Dictionary();
d.set(1, "value1")
d.set(2, "value2")
d.set(3, "value3")
console.log(d.has(2));
d.delete(2);
console.log(d.has(2));

agonza1
fuente
3

¿Qué tal la línea para crear un par de valores clave?

let result = { ["foo"]: "some value" };

y alguna función de iterador como reduceconvertir dinámicamente una matriz a un diccionario

var options = [
  { key: "foo", value: 1 },
  { key: "bar", value: {id: 2, name: "two"} },
  { key: "baz", value: {["active"]: true} },
];

var result = options.reduce((accumulator, current) => {
  accumulator[current.key] = current.value;
  return accumulator;
}, {});

console.log(result);

Dan Dohotaru
fuente
3

En javascript moderno (ES6 / ES2015), uno debe usar la estructura de datos del Mapa para el diccionario. La estructura de datos del Mapa en ES6 le permite usar valores arbitrarios como claves.

const map = new Map();
map.set("true", 1);
map.set("false", 0);

Si todavía usa ES5, la forma correcta de crear un diccionario es crear un objeto sin un prototipo de la siguiente manera.

var map = Object.create(null);
map["true"]= 1;
map["false"]= 0;

Hay muchas ventajas de crear un diccionario sin un objeto prototipo. A continuación, vale la pena leer los blogs sobre este tema.

dict-pattern

objetos como mapas

Jyoti Prasad Pal
fuente
2

Sería de gran ayuda saber cuál es el resultado final deseado, pero creo que esto es lo que quieres:

var vars = [{key:"key", value:"value"}];

vars.push({key: "newkey", value: "newvalue"})
gddc
fuente
2

Me encontré con este problema ... pero dentro de un bucle for. La solución principal no funcionó (cuando se usaban variables (y no cadenas) para los parámetros de la función push), y las otras no contabilizaban los valores clave basados ​​en variables. Me sorprendió que este enfoque (que es común en PHP) funcionó ...

  // example dict/json                  
  var iterateDict = {'record_identifier': {'content':'Some content','title':'Title of my Record'},
    'record_identifier_2': {'content':'Some  different content','title':'Title of my another Record'} };

  var array = [];

  // key to reduce the 'record' to
  var reduceKey = 'title';

  for(key in iterateDict)
   // ultra-safe variable checking...
   if(iterateDict[key] !== undefined && iterateDict[key][reduceKey] !== undefined)
    // build element to new array key
     array[key]=iterateDict[key][reduceKey];
redcap3000
fuente
1

Una mejora en var dict = {}es usar var dict = Object.create(null).

Esto creará un objeto vacío que no tiene Object.prototypecomo prototipo.

var dict1 = {};
if (dict1["toString"]){
    console.log("Hey, I didn't put that there!")
}
var dict2 = Object.create(null);
if (dict2["toString"]){
    console.log("This line won't run :)")
}
WoodenKitty
fuente
1

Primera matriz de inicialización a nivel mundial

var dict = []

Agregar objeto al diccionario

dict.push(
     { key: "One",value: false},
     { key: "Two",value: false},
     { key: "Three",value: false});

Output : 
   [0: {key: "One", value: false}
    1: {key: "Two", value: false}
    2: {key: "Three", value: false}]

Actualizar objeto del diccionario

Object.keys(dict).map((index) => {        
  if (index == 1){
    dict[index].value = true
  }
});

Output : 
   [0: {key: "One", value: false},
    1: {key: "Two", value: true},
    2: {key: "Three", value: false}]

Eliminar objeto del diccionario

Object.keys(dict).map((index) => {              
      if (index == 2){
        dict.splice(index)
      }
    });

Output : 
    [0: {key: "One", value: false},
     1: {key: "Two", value: true}]
Pratik Panchal
fuente