TypeScript, цикл по словарю


186

В моем коде у меня есть пара словарей (как предложено здесь ), которые проиндексированы в виде строки. Из-за того, что это что-то вроде импровизированного типа, мне было интересно, есть ли какие-нибудь предложения о том, как я смогу пройтись по каждому ключу (или значению, все, для чего мне все равно нужны ключи). Любая помощь приветствуется!

myDictionary: { [index: string]: any; } = {};

Пробовали ли вы: for (var key in myDictionary) { }? Внутри цикла вы будете использовать, keyчтобы получить ключ и myDictionary[key]получить значение
Ян

@Ian Только что попробовал, похоже, не работает. Никаких ошибок, но в заявлении ничего не работает
ben657

1
@Ian Извините, какой-то код где-то с этим работал. Это работает отлично! Хотите сделать ответ, чтобы я мог выбрать его?
ben657

Ответы:


296

Чтобы перебрать ключ / значения, используйте for inцикл:

for (let key in myDictionary) {
    let value = myDictionary[key];
    // Use `key` and `value`
}

8
Это не безопасно в целом; ему нужен тест hasOwnProperty (как в ответе Джейми Старка) или что-то еще.
Дон Хэтч

20
@DonHatch На самом деле это вообще очень безопасно. Это небезопасно в очень специфических случаях (например, когда вы включаете библиотеки, которые изменяют прототипы неправильно или намеренно изменяют прототипы). Разработчик должен решить, стоит ли раздувать свой код с помощью, скорее всего, ненужных проверок
Ян

1
@Ian - Я думаю, что я бы не использовал его без дополнительных мер безопасности, так как кажется, что произошел несчастный случай, ожидающий, например, если код попадает в служебную функцию, а затем кто-то передает эту функцию в словарь, который не просто Объект, а точнее что-то с дополнительными свойствами. Да, как вы говорите, разработчик должен взвесить вероятность и серьезность такого сценария. Для меня наименее обременительный подход - вести себя так, как будто такой сценарий гарантированно случится во всех случаях - меньше думать.
Дон Хэтч

5
@Ian Проблема в том, что существует слишком много библиотек, которые модифицируют прототипы объектов. Кажется плохой идеей защищать этот тип паттерна, когда существуют намного лучшие простые альтернативы, такие как Object.keys(target).forEach(key => { let value = target(key); /* Use key, value here */ });. Если вы должны показать этот метод, хотя бы упомяните риски и лучшие альтернативы для тех, кто еще не знает лучше.
Йона Апплетри

8
У нас уже есть es6 и TypeScript. Почему проблема написания hasOwnProperty все время остается нерешенной? Даже в 2017 году и со всем вниманием к JS. Я так разочарован.
Герман,

170

<ES 2017 :

Object.keys(obj).forEach(key => {
  let value = obj[key];
});

> = ES 2017 :

Object.entries(obj).forEach(
  ([key, value]) => console.log(key, value);
);

Это решение, которое я искал, так как оно позволит мне отсортировать ключи перед итерацией
Эндрю

К вашему сведению, в настоящее время это не поддерживается игровой площадкой TypeScript.
Seanny123

1
Смотрите здесь, как заставить Object.entriesработать на TypeScript
Алекс Клаус

Это прекрасно
Пиюш Чоудхари

67

Как насчет этого?

for (let [key, value] of Object.entries(obj)) {
    ...
}

1
Требуется lib es2017 в tsconfig. См. Stackoverflow.com/questions/45422573/…
Стефан

Это то, что мне нужно было, чтобы обойти ошибку Typescript в obj [ключ] «Нет подписи индекса ...», потому что я явно установил свой тип obj как {[key: string]: string} и не хотел использовать {[key: строка]: любая}. С этим я могу просто получить доступ к «стоимости». Спасибо
ggedde

А если вы хотите keyвообще игнорировать , просто оставьте это поле пустым [ , value]. (Спасибо за комментарий к этой проблеме .)
Доминик

51

Есть одно предостережение о цикле ключ / значение, о котором говорил Ян. Если возможно, что у Объектов могут быть атрибуты, связанные с их Прототипом, и когда вы используете inоператор, эти атрибуты будут включены. Поэтому вам нужно убедиться, что ключ является атрибутом вашего экземпляра, а не прототипа. Старые IE известны тем, что indexof(v)появляются в качестве ключа.

for (const key in myDictionary) {
    if (myDictionary.hasOwnProperty(key)) {
        let value = myDictionary[key];
    }
}

3
Не пытаясь разбить волосы, но так как мы говорим о скрипте типа, разве вы не должны использовать let key вместо var key? Хороший ответ, спасибо.
Люк Дюпен

3
На самом деле с текущей версией скрипта типа то keyи valueможет быть const.
Патрик Дежарден

Лучше не вызывать hasOwnPropertyпроверку из целевого объекта, вместо этого сделайте следующее: ...if (Object.prototype.hasOwnProperty.call(myDictionary, key))...Иначе, если вы используете eslint с no-prototype-builtinsправилом, оно выдаст ошибку.
sceee

6

Кратчайший способ получить все значения словаря / объекта:

Object.keys(dict).map(k => dict[k]);

1

Чтобы получить ключи:

function GetDictionaryKeysAsArray(dict: {[key: string]: string;}): string[] {
  let result: string[] = [];
  Object.keys(dict).map((key) =>
    result.push(key),
  );
  return result;
}

1

Ответ Ians хорош, но вы должны использовать const вместо let для ключа, потому что он никогда не обновляется.

for (const key in myDictionary) {
    let value = myDictionary[key];
    // Use `key` and `value`
}
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.