Как создать словарь и динамически добавлять пары ключ-значение?

324

Из поста:

Отправка массива JSON для получения в виде словаря <string, string>

Я пытаюсь сделать то же самое, что и этот пост. Единственная проблема заключается в том, что я не знаю, какие ключи и значения заранее. Поэтому мне нужно иметь возможность динамически добавлять пары ключ и значение, и я не знаю, как это сделать.

Кто-нибудь знает, как создать этот объект и динамически добавлять пары ключ-значение?

Я пробовал:

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

Но это не работает.

KenEucker
источник
2
Работает отлично. console.log (вары); покажи мне [Object key: "newkey" значение: "newvalue" proto : Object]
Алекс Плютау
За исключением того, что это список, а не словарь: \ Я думаю, что данные лучше представить в виде списка "пар", например list = [["key1","value1"],["key2","value2"]]. Некоторые другие языки имеют тип «пара» или «кортеж». Tldr для фактического добавления dict:dict['key'] = "value"
Джордан Стюарт

Ответы:

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

По сути, вы создаете литерал объекта с двумя свойствами (называемыми keyи value) и вставляете его (используя push()) в массив.


Редактировать: Таким образом, почти 5 лет спустя, этот ответ получает отрицательные отзывы, потому что он не создает «нормальный» литерал объекта JS (он же map, он же hash, он же словарь).
Это будет , однако создание структуры , что ОП просили (и который проиллюстрирован на другой вопрос связан с), который является массивом литералов объектов , каждый из которых имеет keyи valueсвойства. Не спрашивайте меня, почему эта структура была необходима, но это та, которую просили.

Но, если, что вы хотите в простом объекте JS - а не в структуре, которую запрашивал OP, - см . Ответ tcll , хотя обозначение в скобках немного громоздко, если у вас просто простые ключи, которые являются действительными именами JS. Вы можете просто сделать это:

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

Или используйте обычные точечные обозначения для установки свойств после создания объекта:

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

Вы действительно хотите , кронштейн обозначения , если у вас есть ключи , которые имеют пробелы в них, специальные символы, или тому подобное. Например:

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

Вам также нужна скобочная запись, если ваши ключи динамические:

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

Обратите внимание, что ключи (имена свойств) всегда являются строками, а не строковые значения будут приводиться к строке при использовании в качестве ключа. Например, Dateобъект преобразуется в его строковое представление:

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

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

Однако обратите внимание, что это не обязательно «просто работает», так как многие объекты будут иметь строковое представление, подобное тому, "[object Object]"которое не создает неуникальный ключ. Так что будьте осторожны с чем-то вроде:

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

Несмотря на objAи objBбыть совершенно разными и уникальными элементы, они оба имеют одинаковое строковое представление: "[object Object]".

Причина Dateне в том, что Dateпрототип имеет собственный toStringметод, который переопределяет строковое представление по умолчанию. И вы можете сделать то же самое:

// 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"
//    }

(Обратите внимание, что поскольку в приведенном выше примере используется случайное число, коллизии имен могут по-прежнему происходить очень легко. Это просто для иллюстрации реализации toString.)

Поэтому при попытке использовать объекты в качестве ключей JS будет использовать собственную toStringреализацию объекта , если таковая имеется, или использовать строковое представление по умолчанию.

Flambino
источник
2
Это ассоциативно?
Чаба Тот
1
@ CsabaToth Нет, dictэто не ассоциативный словарь. Это массив объектов, каждый из которых похож на словарь с двумя ключами: «ключ» и «значение».
Роман Старков
1
У вас есть массив, который просто называется «dict».
Ян Кью Пеблик
2
Цените обновление и следите за дополнительной информацией.
Джейкоб
411
var dict = {};

dict['key'] = "testing";

console.log(dict);

работает как питон :)

консольный вывод:

Object {key: "testing"} 
Tcll
источник
3
Это, безусловно, лучший подход к созданию словаря, и это правильный ответ!
Роман
3
Очень важно инициализировать скобками, {}а не круглыми скобками
Jaider
В качестве словарей я также использую базовые объекты. Рад видеть, что это правильный путь!
TKoL
5
«Красота» JavaScript! Объект действительно представляет собой сам словарь пары «ключ-значение»
100
1
@Azurespot ключ может быть чем угодно, ключи в конце концов упорядочены по хешу, который в python3 отличается при каждом запуске.
Tcll
53

Это так же просто, как:

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

или

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

затем

blah.key3 = value3; // add a new key/value pair
blah.key2; // returns value2
blah['key2']; // also returns value2
Саймон Саррис
источник
1
@KenEucker Я думаю, что в таких вопросах полезно иметь неправильные ответы. Особенно, если кто-то объясняет, почему они не правы, это хороший учебный ресурс.
CJBrew
32

Поскольку вы заявили, что вам нужен объект словаря (а не массив, как я полагаю, некоторые поняли), я думаю, что вы ищете:

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
ZenMaster
источник
Другое решение, использующее .push в массиве, подходит для моего использования, но я предполагаю, что это также будет работать, если я попробую.
KenEucker
2
Если я неправильно понимаю, что такое объект Dictionary, тогда ваш вопрос вводит в заблуждение. Как бы вы получили значение по ключу из вашего массива?
ZenMaster
Я использую JSON.stringify для этого объекта, а затем перехватываю его с помощью контроллера в MVC 3. Это просто для того, чтобы он был правильно отформатирован перед его форматированием и последующей отправкой.
KenEucker
23

В JavaScript Object является сам по себе , как словарь. Не нужно изобретать велосипед.

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
}

скрипка

Яни Хюйтяйнен
источник
11

Вы можете использовать карты Map, например:

var sayings = new Map();
sayings.set('dog', 'woof');
sayings.set('cat', 'meow');
Preetham Kumar P
источник
9

Мне довелось пройтись по этому вопросу в поисках чего-то похожего. Это дало мне достаточно информации, чтобы выполнить тест, чтобы получить ответ, который я хотел. Поэтому, если кто-то еще хочет знать, как динамически добавлять или искать пару {ключ: 'значение'} в объекте JavaScript, этот тест должен рассказать вам все, что вам может понадобиться знать.

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

вывод

initialValue
{ initialkey: 'initialValue',
  something: 'value1',
  somethingElse: 'value2' }
user2301449
источник
2
Это не вопрос. Вместо этого вам следует задать вопрос, а затем ответить на него самостоятельно. Это было бы намного легче понять и организовать.
SalmonKiller
1
спасибо @SalmonKiller я не был уверен в правильной терминологии, чтобы написать свой собственный вопрос и ожидать, что он будет понят, но потом я наткнулся на это в моем поиске, вся информация была там, но распределена между несколькими ответами, поэтому я ответил на концепцию этого вопроса в таким образом, это ответило бы для кого-то еще, кто наткнулся на этот вопрос, ища то же самое, что и я
user2301449
1
РЖУНИМАГУ. Я рассматривал это, и это было похоже на вопрос, а не на ответ. Извини чувак!
SalmonKiller
Спасибо за добавление этого. Вы также можете поместить это в скрипку, как ответ выше.
KenEucker
8
var dictionary = {};//create new object
dictionary["key1"] = value1;//set key1
var key1 = dictionary["key1"];//get key1
SharpCoder
источник
для некоторой дополнительной производительности вы должны ссылаться, key1 = dictionary.key1а не индексироватьkey1 = dictionary["key1"]
Tcll
4

Вы можете создать класс Dictionary, чтобы вы могли легко взаимодействовать со списком Dictionary:

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
источник
3

как насчет одного лайнера для создания пары ключ-значение?

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

и некоторые итераторы любят reduceдинамически преобразовывать массив в словарь

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

Дан Дохотару
источник
3

В современном javascript (ES6 / ES2015) следует использовать структуру данных Map для словаря. Структура данных карты в ES6 позволяет использовать произвольные значения в качестве ключей.

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

Если вы все еще используете ES5, правильный способ создания словаря - создать объект без прототипа следующим образом.

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

Есть много преимуществ создания словаря без объекта-прототипа. Ниже блоги стоит почитать на эту тему.

ДИКТ-паттерн

объекты-как-карты

Джиоти Прасад Пал
источник
2

Это помогло бы многим узнать, каков ваш конечный желаемый результат, но я думаю, что это то, что вы хотите:

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

vars.push({key: "newkey", value: "newvalue"})
gddc
источник
2

Я столкнулся с этой проблемой .. но в рамках цикла. Верхнее решение не работало (при использовании переменных (а не строк) для параметров функции push), а другие не учитывали значения ключей, основанные на переменных. Я был удивлен, что этот подход (который распространен в php) работал ..

  // 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
источник
1

Улучшение var dict = {}заключается в использовании var dict = Object.create(null).

Это создаст пустой объект, который не имеет Object.prototypeсвоего прототипа.

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
источник
1

Первая инициализация массива глобально

var dict = []

Добавить объект в словарь

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

Обновить объект из словаря

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

Удалить объект из словаря

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

Output : 
    [0: {key: "One", value: false},
     1: {key: "Two", value: true}]
Пратик Панчал
источник