将对象的平面数组转换为具有动态结构的深层嵌套对象(树) [英] Flat array of objects into deep nested object (tree) with dynamic structure

查看:24
本文介绍了将对象的平面数组转换为具有动态结构的深层嵌套对象(树)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我为静态结构找到了很多解决方案,但对于动态结构却一无所获.这是一个简单的用例...

I've found a lot of solutions for a static structure, but nothing for a dynamic one. Here's the simple use case...

let nested = deepNest(array, ["criteria1", "criteria2", ...])

这是想要的结果...

deepNest(people, ["gender", "color"]);

// result
{
    male: {
        blue: {
            0: {name: "Jim", color: "blue", gender: "male"},
            1: {name: "Sam", color: "blue", gender: "male"}
        },
        green: {
            0: {name: "Eddie", color: "green", gender: "male"}
        }
    },
    female: {
        blue: {
            0: {name: "Eva", color: "blue", gender: "female"},
        },
        green: {
            0: {name: "Susan", color: "green", gender: "female"}
        }
    }
}

...基于此数据.

const people = [
  {
    name: "Jim",
    color: "blue",
    gender: "male"
  },
  {
    name: "Susan",
    color: "green",
    gender: "female"
  },
  {
    name: "Sam",
    color: "blue",
    gender: "male"
  },
  {
    name: "Eddie",
    color: "green",
    gender: "male"
  },
  {
    name: "Eva",
    color: "blue",
    gender: "female"
  }
];

请记住,分组必须是动态的,即数组可以嵌套,如 deepNest(people, ["gender"])deepNest(人物,[颜色",性别",姓名"])

Keep in mind that the grouping has to be dynamic i.e. the array can be nested like deepNest(people, ["gender"]) or deepNest(people, ["color", "gender", "name"])

推荐答案

下面是一些使用递归的代码.它首先找到第一个查询的所有选项,然后使用给定查询具有相同值的对象数组递归调用自身,并且在最深点,如果没有更多查询,则返回对象数组满足所有先前的查询.

Here's some code that works with recursion. It first finds all the options for the first query, and then recursively calls itself with the array of the objects with the same value for the given query, and at the deepest point, if there is no more queries, it returns the array of objects that meet all the previous queries.

我可以回答有关此的任何问题,但我觉得在评论和此描述中对此进行了足够的解释.

I can answer any questions about this, but I feel like this is explained enough in the comments and this description.

const people = [
  {
    name: "Jim",
    color: "blue",
    gender: "male"
  },
  {
    name: "Susan",
    color: "green",
    gender: "female"
  },
  {
    name: "Sam",
    color: "blue",
    gender: "male"
  },
  {
    name: "Eddie",
    color: "green",
    gender: "male"
  },
  {
    name: "Eva",
    color: "blue",
    gender: "female"
  }
];



const deepNest = (arr, [first, ...rest]) => {
  let output = {};
  if (first) {
    let options = [...arr.reduce((set, val) => set.add(val[first]), new Set())].sort(); // Get the options (Set() is a built in thing to remove duplicates), and the sort them alphabetically
    for (let option of options) {
      let val = arr.filter((val) => val[first] === option); // Get the values that have the same value for the option for the query
      output[option] = deepNest(val, rest); // Recursion
    }
  } else {
    output = arr;
  }
  return output;
}

display(deepNest(people, ["gender", "color"]), ["gender", "color"]);
display(deepNest(people, ["color", "gender"]), ["color", "gender"]);
display(deepNest(people, ["color", "name", "gender"]), ["color", "name", "gender"]);

// My own custom display function, since console.log() makes it look wack
function display(json, query) {
  const div = document.createElement("div");
  const h2 = document.createElement("h2");
  h2.innerText = `["${query.join("\", \"")}"]`;
  const pre = document.createElement("pre");
  pre.innerText = JSON.stringify(json, null, 2);
  
  div.appendChild(h2);
  div.appendChild(pre);
  
  document.querySelector("body").appendChild(div);
}

html,
body {
  background: whitesmoke;
}

pre {
  color: black;
  background: white;
  border: 2px solid black;
  border-radius: 1rem;
  padding: 1rem;
}

这篇关于将对象的平面数组转换为具有动态结构的深层嵌套对象(树)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆