#javascript #json #typescript #algorithm
#javascript #json #typescript #алгоритм
Вопрос:
Я пытаюсь написать функцию, которая получает ключ (строку) и возвращает его значения, если он существует в JSON.
Полученный JSON:
[
{
"some_key1": [
{"key": "value1"},
{"key": "value2"},
{"key": "value3"}
]
},
{
"some_key2": [
{"key": "value4"},
{"key": "value5"},
{"key": "value6"}
]
},
{
"default_val": [
{"key": "value7"},
{"key": "value8"},
{"key": "value9"}
]
}
]
Структура выглядит следующим образом, и единственное, что может отличаться, это количество внутренних объектов.
Функция, которая возвращает массив:
interface InnerObject {
key: string;
}
const getValues = (key = "default_val"): InnerObject[] => {
/* working code */
}
Пример ожидаемого результата:
> getValues("some_key2");
[{"key": "value4"},{"key": "value5"},{"key": "value6"}]
> getValues();
[{"key": "value7"},{"key": "value8"},{"key": "value9"}]
Какие-нибудь элегантные решения?
Комментарии:
1. Цикл с
if
.2. @zerkms Я не думаю, что это лучшее, что можно сделать, если у вас есть пара сотен объектов, и вам приходится фильтровать их при каждом нажатии.
3. Я выполняю гораздо более сложную фильтрацию объектов по щелчку с десятками тысяч узлов без видимых проблем. Я не думаю, что производительность, вероятно, является вариантом, пока вы не наберете хотя бы сотни тысяч.
4. @Bart «Я не думаю, что это лучшее, что можно сделать» — нет ничего абсолютно «лучшего»: решение либо соответствует вашим требованиям, либо нет. Учитывая, что у вас вообще ничего нет — любое решение значительно лучше вашего текущего. Тем не менее — если у вас такая неоптимальная структура — чего еще вы ожидаете, кроме итерации по ней?
5. всегда ли ваша структура данных будет точной
[{'some key name':[ {<arbitrary object>}...]}..., {'default_val':[ {<arbitrary object>}...]}]
, и вы хотите вернутьdefault_val
, если ключ не указан, независимо от того, где он находится в массиве?
Ответ №1:
То же решение, что и Nick, но с find
возвращением объекта напрямую:
const data = [
{
"some_key1": [
{"key": "value1"},
{"key": "value2"},
{"key": "value3"}
]
},
{
"some_key2": [
{"key": "value4"},
{"key": "value5"},
{"key": "value6"}
]
},
{
"default_val": [
{"key": "value7"},
{"key": "value8"},
{"key": "value9"}
]
}
];
const getValues = (key = 'default_val') => data.find(o => Object.keys(o)[0] == key);
console.log(getValues('some_key2'));
console.log(getValues());
Комментарии:
1. Нет
getValues = (key = 'default_val') =>…
?2. Если с заданным ключом может быть только одно значение, это лучшее решение, чем мое.
3. @GarrettMotzner Да, действительно, мы можем это сделать. Спасибо!
Ответ №2:
Эта структура не идеальна для поиска. Почему бы сначала не преобразовать его в лучшую структуру и использовать это для поиска?
Что-то вроде этого может сделать:
const makeSearcher = (input, obj = Object .assign (...input)) => (key) =>
obj [key] || obj .default_val
const input = [{some_key1: [{key: "value1"}, {key: "value2"}, {key: "value3"}]}, {some_key2: [{key: "value4"}, {key: "value5"}, {key: "value6"}]}, {default_val: [{key: "value7"}, {key: "value8"}, {key: "value9"}]}]
const search = makeSearcher (input)
console .log (search ('some_key2'))
console .log (search ())
Предполагается, что существует только один объект с заданным ключом. Если нет, я бы обратился к решению Ника.
Хотя это O (1)
функция поиска, логического ответа на этот вопрос, скорее всего, не будет O (n)
, поэтому я не думаю, что производительность в любом случае будет большой проблемой.
Ответ №3:
Это сделает:
const getValues = (key = "default_val"): InnerObject[] => {
return data.find(item => item[key])[key];
};
Ответ №4:
Вы могли бы использовать Array.filter
с проверкой, что ключ объекта совпадает с переданным параметром (или default_val
если он не передан):
const data = [
{
"some_key1": [
{"key": "value1"},
{"key": "value2"},
{"key": "value3"}
]
},
{
"some_key2": [
{"key": "value4"},
{"key": "value5"},
{"key": "value6"}
]
},
{
"default_val": [
{"key": "value7"},
{"key": "value8"},
{"key": "value9"}
]
}
];
const getValues = (key = 'default_val') => data.filter(o => Object.keys(o)[0] == key);
console.log(getValues('some_key2'));
console.log(getValues());
Этот код вернет несколько значений, если существует более одного значения с одним и тем же ключом поиска. Если нет, то более эффективно использовать Array.find
, как описано в некоторых других ответах.
Ответ №5:
Вот более общее решение с использованием object-scan
Основное преимущество заключается в том, что его очень легко настроить, например. более глубокие ключи и несколько ключей.
// const objectScan = require('object-scan');
const myData = [{ some_key1: [{ key: 'value1' }, { key: 'value2' }, { key: 'value3' }] }, { some_key2: [{ key: 'value4' }, { key: 'value5' }, { key: 'value6' }] }, { default_val: [{ key: 'value7' }, { key: 'value8' }, { key: 'value9' }] }];
const find = (data, key) => objectScan([key], { reverse: false, rtn: 'value' })(data)
console.log(find(myData, '[*].some_key2[*]'));
// => [ { key: 'value4' }, { key: 'value5' }, { key: 'value6' } ]
.as-console-wrapper {max-height: 100% !important; top: 0}
<script src="https://bundle.run/object-scan@13.8.0"></script>
Отказ от ответственности: я автор object-scan