Уменьшить массив свойств объекта до вложенного объекта

#javascript #arrays #reduce

#javascript #массивы #уменьшить

Вопрос:

У меня есть массив с возрастающей специфичностью, например.

 const locationProperties = ['earth', 'americas', 'canada', 'saskatchewan'];

 

и я хотел бы, чтобы объект:

 {
 earth: {
  americas: {
   canada: {
    saskatchewan: {
      // data 
    }
   }  
  }
 }
}
 

Я думал использовать .reduce для создания объекта, но после применения преобразования в редукторе у меня осталось только {}

 const reducer = (accumulator, item) => {
  accumulator[item] = {};
  return accumulator[item];
}

const reducedArray = locationProperties.reduce(reducer, {});
 

Ответ №1:

Я бы рекомендовал простую функцию рекурсии, nest

 const nest = ([key, ...more], val) =>
  key == null
    ? val
    : {[key]: nest(more, val)}
    
const loc =
  ['earth', 'americas', 'canada', 'saskatchewan']    

console.log(nest(loc, "something")) 

 {
  "earth": {
    "americas": {
      "canada": {
        "saskatchewan": "something"
      }
    }
  }
}
 

Вы также можете использовать reduceRight

 const loc =
  ['earth', 'americas', 'canada', 'saskatchewan']    

const result =
  loc.reduceRight((val, key) => ({[key]: val}), "something")

console.log(result) 

 {
  "earth": {
    "americas": {
      "canada": {
        "saskatchewan": "something"
      }
    }
  }
}
 

Поскольку вы знакомы с reduce , я укажу, что arr.reduceRight(...) это фактически эквивалент arr.reverse().reduce(...) . Однако использование reduceRight в этом случае более эффективно и не приведет к изменению входного массива —

 const loc =
  ['earth', 'americas', 'canada', 'saskatchewan']    

const result =
  loc.reverse().reduce((val, key) => ({[key]: val}), "something")

console.log(result) 

 {
  "earth": {
    "americas": {
      "canada": {
        "saskatchewan": "something"
      }
    }
  }
}
 

Комментарии:

1. Вау. Это красиво. Мне очень нравится это решение. Я также пытался решить этот вопрос, но мой не такой красивый, как ваш. Я думаю, будет более совершенным, если вы измените аргумент "something" на {} ?

2. Спасибо за комментарий, Miu. Я действительно ценю это. Я сделал внутреннюю переменную "something" , чтобы сигнализировать, что это может быть все, что захочет вызывающий. Также я не хотел, чтобы люди путались, думая {} , что это начало самого внешнего объекта.

3. Я понял 🙂 Спасибо за ваш любезный ответ. Теперь я полностью согласен с вами и «кое-что» 🙂