【问题标题】:Flat array of objects into deep nested object (tree) with dynamic structure [closed]将平面对象数组转换为具有动态结构的深层嵌套对象(树)[关闭]
【发布时间】:2021-03-13 02:19:38
【问题描述】:

我找到了很多静态结构的解决方案,但没有找到动态结构的解决方案。这是一个简单的用例......

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(people, ["color", "gender", "name"]) 一样嵌套

【问题讨论】:

  • 你的deepNest在哪里?
  • 请访问help center,使用tour查看内容和How to Ask。做一些研究,搜索关于SO的相关主题;如果您遇到困难,请发布您的尝试minimal reproducible example,并使用[<>] sn-p 编辑器记录输入和预期输出。
  • Stack Overflow 的一条规则是,您需要展示一次尝试,而不仅仅是说“在这里,为我做这件事”。我将为您做的是给您提示:研究使用Array.prototype.sort()Array.prototype.filter(),还使用字符串索引对象:window.console.log("oh wow!")window["console"]["log"]("oh wow!") 相同,诸如此类。
  • 顺便问一下,这个的用例是什么?我想不出一个,但你可能确实有一个用例,因为你说它“超级有用”。 ¯\_(ツ)_/¯

标签: javascript arrays object tree


【解决方案1】:

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

我可以回答有关此的任何问题,但我觉得这在 cmets 和此描述中已经得到了足够的解释。

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;
}

【讨论】:

  • @Ivan 我已经更新了数据的显示方式,希望它看起来更好。 (向 DOM 添加东西而不是 console.log'ging 对于这样的事情在 imo 中看起来更好)
  • “我会尝试了解它是如何工作的”如果您想了解更多信息,请提出一些问题。我不知道你的技术水平,所以我不知道该解释什么。
  • 住手,我只能挺直了!!!我的水平能看懂你的代码,还不够好想出来。这段代码是一件艺术品,说真的。这条线...arr.reduce((set, val) => set.add(val[first]), new Set()) daaaaamn...我得到了一切,我只是无法创建它,因此我的问题。令人难以置信的工作,我被炒作了。我渴望拥有接近这种优雅的机智。
  • 我通过按字母顺序对选项数组进行排序,使每个孩子的按键顺序相同,从而使这一点稍微好一点。它在数据方面没有做任何事情,但是 1) 它看起来更好/更干净,2) 原因 #1 是唯一的原因。
  • @mplungjan “展示”是指简单的 CSS 和 [显示到 DOM]?当然,为什么不呢?我没有发明 css 或其他任何东西,但 whitesmoke 主背景、白色背景 <pre> 带有 1rem 填充、2px 纯黑色边框和 1rem 半径的标签是我正在开发的 webapp 的风格,所以我把它拿过来让它看起来不错。你绝对可以使用那些东西。 (JSON.stringify(aJSONObject, null, spacesToIndent) 是一个很好的函数,可以用适当的缩进对 JSON 进行字符串化,我绝对没有这样做)
猜你喜欢
  • 2022-11-24
  • 2023-03-18
  • 1970-01-01
  • 2020-01-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-09-23
相关资源
最近更新 更多