У меня есть строка и список словарей в JavaScript/TypeScript, и я пытаюсь найти эту строку в любом словаре, в котором она находится (она может быть только в одной записи), и вернуть значение, хранящееся в числовом ключе в словаре. . Я делаю это, перебирая свой список и сравнивая сохраненное значение с моей входной строкой. Все словарные метки и числовые записи уникальны.
var myString = "ABC";
var output = 0;
const listOfDicts = [
{label: "ABC", number: 10},
{label: "DEF", number: 20},
{label: "GHI", number: 30},
];
listOfDicts.forEach((e) => {
if (e.label === myString) {
output = e.number;
}
});
Это наиболее эффективный способ присвоить 10 моему выводу или есть умный однострочный способ сделать это, о котором я не знаю? Обратите внимание, что если бы моя структура была картой, я мог бы просто использовать метод .get(myString) для возврата соответствующего значения, но у меня нет карты, поэтому мы здесь.
Вы делаете это неоднократно с одним и тем же listOfDicts? Это определяет, стоит ли конвертировать его в Map.
@Ry- большое спасибо за обе идеи. И нет, я не делаю повторных вызовов listOfDicts, поэтому наличие карты + списка dicts мне нежелательно.



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Вы можете использовать метод find, чтобы сделать код более кратким и потенциально более читабельным.
const myString = "ABC";
let output = 0;
const listOfDicts = [
{label: "ABC", number: 10},
{label: "DEF", number: 20},
{label: "GHI", number: 30}
];
const found = listOfDicts.find(e => e.label === myString);
if (found) {
output = found.number;
}
console.info(output);Метод find возвращает первый элемент массива, который удовлетворяет предоставленной функции тестирования. Если ни один элемент не удовлетворяет функции тестирования, она возвращает undefined. Поэтому перед доступом к свойству found рекомендуется проверить, не является ли undefinednumber.
Если вы хотите сделать это в одной строке, вы можете использовать необязательный оператор цепочки (?.) и нулевой оператор объединения (??) для обработки случая, когда элемент не найден:
const myString = "ABC";
const listOfDicts = [
{label: "ABC", number: 10},
{label: "DEF", number: 20},
{label: "GHI", number: 30}
];
const output = (listOfDicts.find(e => e.label === myString)?.number) ?? 0;
console.info(output);Поскольку ваш listOfDicts представляет собой массив объектов, вы можете использовать метод find для поиска соответствующего объекта, и если совпадение найдено, вы получите номер, например:
var myString = "ABC";
let match = listOfDicts.find(x => x.label === myString);
if (match) output = match.number;
Метод find принимает предоставленную вами функцию для поиска совпадения.
Вы упомянули «эффективность». Если вы собираетесь вызвать функцию один раз, наиболее эффективной стратегией будет та, которую вы изложили: перебор списков с использованием метода find() и проверка каждого из них.
Но если вы собираетесь просматривать один и тот же список несколько раз, возможно, будет эффективнее сделать следующее:
const makeSearch = (listOfDicts: Array<{ label: string; number: number }>) => {
const allObjects = Object.fromEntries(listOfDicts.map(({ label, number }) => [label, number]));
return (key: string) => allObjects[key];
}
....
const search = makeSearch([
{label: "ABC", number: 10},
{label: "DEF", number: 20},
{label: "GHI", number: 30}
]);
const output = search("ABC");
Map более уместен, чем объект — лучше вообще не думать о Object.prototype.
Эффективным подходом для нескольких поисков будет загрузка списка на карту и поиск по нему:
var myString = "ABC";
var output = 0;
const listOfDicts = [
{label: "ABC", number: 10},
{label: "DEF", number: 20},
{label: "GHI", number: 30},
];
const map = new Map(listOfDicts.map(e => [e.label, e.number]));
output = map.get(myString) ?? 0;
console.info(output);
listOfDicts.map(Object.values) as [string, number][] хрупкий по сравнению с более коротким, более читабельным и эффективным listOfDicts.map(e => [e.label, e.number]).
@Ry- согласен, но мне нужна была магия Object.values(), жаль, что она не возвращает кортеж, исправлено с помощью твоего варианта, спасибо
К сожалению, на мой список диктовок ссылаются слишком много мест во всем коде, чтобы мне было удобно его менять, и я бы предпочел не иметь лишнего беспорядка в виде списка и карты, иначе я бы использовал карту. Спасибо за ваш ответ и за то, что показали мне, как преобразовать мой список в карту.
e.label.toLowerCase === myString.toLowerCaseсравнивает функции (всегда верно), а не вызывает их (.toLowerCase()в скобках). Один вопрос на вопрос.