Доступ к свойству объекта из массива ключей - PullRequest
0 голосов
/ 10 октября 2018

Я хочу написать вспомогательную функцию для распаковки определенного свойства объекта из каждого объекта в массиве объектов.Иногда это свойство будет верхнего уровня, в других случаях оно будет вложено произвольное количество уровней.Итак, суть этого вопроса: как я могу получить доступ к свойству объекта на основе массива имен ключей переменной длины?

Я надеюсь на что-то вроде:

const func = (arrOfObjects, ...keys) {
    return arrOfObjects.map(object => {
        return object[keys[0]][keys[1]] ... [keys[N]];
    })
}

спример поведения:

const input = [
    {a: b: {c: 10}},
    {a: b: {c: 11}},
    {a: b: {c: 12}}
]

console.log(func(input, 'a', 'b', 'c'))
// [10, 11, 12]
console.log(func(input, 'a', 'b'))
// [{c: 10}, {c: 11}, {c : 12}]

Я чувствую, что должно быть хорошее решение ES6 для волшебников, но пока не нашел его, поэтому любая помощь будет высоко ценится!

Приветствия,

P

Ответы [ 3 ]

0 голосов
/ 10 октября 2018

Вы можете получить короткое и простое решение, используя Массив # уменьшить

const input = [
    {a: { b: {c: 10}}},
    {a: { b: {c: 11}}},
    {a: { b: {c: 12}}}
]


console.log(func(input, ['a', 'b', 'c']))
// [10, 11, 12]
console.log(func(input, ['a', 'b']))
// [{c: 10}, {c: 11}, {c : 12}]

function func(input, props) {
  return input.map(x => exctractByProps(x, props));
}

function exctractByProps(obj, props) {
  return props.reduce( 
    (acc, prop) => typeof acc === 'object' && prop in acc ? acc[prop] : undefined, 
    obj 
  )
}

Основная логика - захватить все переданные свойства и затем попытаться получить значение, соответствующее obj[prop[0]][prop[1]][prop[2]]/* ... */[prop[n]].Если объект имеет странную форму, которая не совпадает с prop (например, ввод {a: 1}, ['a', 'b'] или {d: {c: 1}}, ['a', 'b']), тогда функция возвращает undefined.

0 голосов
/ 10 октября 2018

На основании ответов, которые вы дали мне на мои вопросы, и вашего примера.Кажется, что порядок ввода всегда будет соответствовать вложенности объектов.Итак, вот мое решение:

const func = (arrOfObjects, ...keys) => {
  return arrOfObjects.map(object => {
    let obj = object, integer = keys.length;
    for (let index = 0; index < integer; index++) {
      obj = obj[keys[index]];
      if(obj === undefined) break;
    }
    return obj;
  });
};

const input = [
  { a: { b: { c: 10 } } },
  { a: { b: { c: 11 } } },
  { a: { b: { c: 12 } } }
];

console.log(func(input, "a", "b", "c"));
// [10, 11, 12]
console.log(func(input, "a", "b"));
// [{c: 10}, {c: 11}, {c : 12}]

К сожалению, нет такой вещи, как магия javascript, которую вы ожидаете. Примечание: этот код не будет работать, если порядок ключей внутри объекта расположен на произвольной глубине.Но то, что вы пытаетесь решить, это должно работать просто отлично.Также я постарался сохранить ваш исходный код как можно лучше

0 голосов
/ 10 октября 2018

Если вы предоставляете метод доступа, например [a, b, c[0], name], вы можете написать пользовательскую функцию, которая возвращает значение, если оно найдено во вложенном объекте, в противном случае возвращает неопределенное значение

 let obj = {
   a: 1,
   b: 2,
   c: {
     d: 1,
     e: [{
       f: 3,
       g: [{
         z: 45
       }]
     }]
   }
 }
function findKeyFromPattern(obj, patternArr) {
  let value = obj;
  for(let i = 0; i < patternArr.length; i++) {
    const arrmatch = patternArr[i].match(/(\w+)\[(\d+)\]/);
    if(arrmatch) { // pattern matches and array accessor syntax
      value = value[arrmatch[1]];
      if(typeof value === 'object' && value !== null) {
        value = value[arrmatch[2]];
      } else {
        return;
      }
    } else {
      if(value[patternArr[i]]) {
        value = value[patternArr[i]];
      } else {
        return;
      }
    }
  }
  return value;
}


console.log(findKeyFromPattern(obj, ['c', 'e[0]', 'g']));
console.log(findKeyFromPattern(obj, ['c', 'e[1]', 'g']))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...