【问题标题】:how to transform nested Object array to an Object with its 'id' as key?如何将嵌套对象数组转换为以“id”为键的对象?
【发布时间】:2018-11-15 01:07:42
【问题描述】:

我有一些这样的数据,因为嵌套对象很难在redux中设置状态,所以我想将它转换为以id为键的对象。这样我就可以轻松地改变状态。我搜索了一整天,但没有找到方法

// here is the source data
// every object has an id property
// outer object has 2 or 3 levels: continents -> countries || continents -> countires -> regions

    const source = [
      {
        id: 2,
        name: "King",
        continents: [
          {
            id: 12,
            name: "Africa",
            abbr: null,
            countries: [
              {
                id: 13,
                name: "South Africa",
                abbr: "aa.jpg"
              }
            ]
          },
          {
            id: 5,
            name: "European",
            abbr: null,
            countries: [
              {
                id: 7,
                name: "France",
                abbr: "fg.jpg"
              }
            ]
          },
          {
            id: 6,
            name: "North America",
            abbr: null,
            countries: [
              {
                id: 8,
                name: "Denmark",
                abbr: "gg.jpg"
              }
            ]
          }
        ]
      },
      {
        id: 1,
        name: "Elite",
        continents: [
          {
            id: 2,
            name: "South America",
            abbr: null,
            countries: [
              {
                id: 4,
                name: "Brazal",
                abbr: "bx.jpg"
              }
            ]
          },
          {
            id: 5,
            name: "European",
            abbr: null,
            countries: [
              {
                id: 9,
                name: "England",
                abbr: "yg.jpg",
                regions: [
                  {
                    id: 1,
                    name: "England-1",
                    abbr: null,
                    
                  },
                  {
                    id: 10,
                    name: "England-2",
                    abbr: null,
                    
                  }
                ]
              }
            ]
          }
        ]
      }
    ];

如您所见,每个 Object 都有一个 id 字段。我想提取每个 id 作为键,输出如下:

// output
{
  2: {
    id: 2,
    name: "King",
    continents: {
      12: {
        id: 12,
        name: "Africa",
        countries: {
          13: {
            id: 13,
            name: "South Africa"
          }
        }
      },
      6: {
        id: 6,
        name: "North America",
        countries: {
          8: {
            id: 8,
            name: "Denmark"
          }
        }
      },
      5: {
        id: 5,
        name: "European",
        countries: {
          7: {
            id: 7,
            name: "France"
          }
        }
      }
    }
  },
  1: {
    id: 1,
    name: "Elite",
    continents: {
      2: {
        id: 2,
        name: "South America",
        countries: {
          4: {
            id: 4,
            name: "Brazal"
          }
        }
      },
      5: {
        id: 5,
        name: "European",
        countries: {
          9: {
            id: 9,
            name: "England",
            regions: {
              1: {
                id: 1,
                name: "England-1"
              },
              2: {
                id: 2,
                name: "England-2"
              }
            }
          }
        }
      }
    }
  }
}

我认为我应该使用递归什么的,我什至尝试使用 ramda.js,但仍然没有运气!

【问题讨论】:

    标签: javascript algorithm


    【解决方案1】:

    创建一个函数将数组转换为查找对象:

      const toLookup = (array, key) => array.reduce((obj, el) => (obj[ el[key] ] = el, obj), {});
    

    然后另一个遍历和映射所有嵌套属性:

     function traverse (mapper, root) {
       const result = {};
       for(let [k, v] of Object.entries(root)) {
         v = mapper(v, k);
         if(typeof v === "object" && !Array.isArray(v) && v !== null)
           v = traverse(mapper, v);
         result[k] = v;
      }
      return result;
    }
    

    现在使用它并将每个数组转换为查找对象:

     const result = traverse(
      it => Array.isArray(it) ? toLookup(it, "id") : it,
      toLookup(source, "id")
    );
    

    【讨论】:

    • 非常感谢!你是个天才。你拯救了我的一天!
    猜你喜欢
    • 1970-01-01
    • 2021-05-28
    • 1970-01-01
    • 2020-07-03
    • 1970-01-01
    • 1970-01-01
    • 2018-01-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多