Получение значения из ключа вложенного объекта JSON

#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