- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
可能重复,但这与其他问题不同,它不希望将对象挂接到另一个问题。我想创建一个包含层次结构数据的新对象/数组
所以我有这些数据集:
var sets = {
'dataSet1': {
'ID': '1',
'ParentID': '0'
},
'dataSet2': {
'ID': '2',
'ParentID': '1'
},
'dataSet3': {
'ID': '3',
'ParentID': '1'
},
'dataSet4': {
'ID': '4',
'ParentID': '3'
}
}
var tiers = {
'tier1':[
{
'parentid':'0',
'id':'1'
}
]
,'tier2':[
{
'parentid':'1',
'id':'2'
},
{
'parentid':'1',
'id':'3'
}
]
,'tier3':[
{
'parentid':'3',
'id':'4'
}
]
}
var datasetobj = sets;
var hierarchy = tiers;
for (x in datasetobj) {
if (datasetobj[x]['ParentID'] == 0) {
hierarchy['tier1'].push({
'parentid': datasetobj[x]['ParentID'],
'id': datasetobj[x]['ID']
});
}
}
最佳答案
您的问题需要遍历依赖关系树,同时跟踪深度。您可以使用简单的depth-first-traversal来解决问题,该recursion使用递归并增加深度。
由于缺乏解释,我不得不道歉。如果您以后需要它们,我将添加更多详细信息,但我必须运行。希望这有助于解决您的问题。让我知道是否需要更多说明。
我还已将originalKey
属性添加到分层对象,以便您可以使用originalKey
访问原始对象。
更新:好的,您想要更多的解释,您将获得更多的解释。我还更改了实现以使其速度更快。
此外,您能否提供一些链接,以链接到我可以研究这些概念的地方?您的方法对我来说是很新的
只有使用sets
和一些基本的计算机科学概念才能真正解决此问题。我将解释代码,并提供一些指向良好计算机科学概念的链接。概念并不太复杂。这些是您在计算机科学本科课程中首先要学习的东西。
将hashMap
转换为sets
我要做的第一件事是将您的hashMap
对象转换为另一个我称为tier
的对象。我将其转换为这种形式,因为在创建sets
对象时,它将使“查找”更快。
这是Object.keys
对象供参考:
const sets = {
'dataSet1': {
'ID': '1',
'ParentID': '0'
},
'dataSet2': {
'ID': '2',
'ParentID': '1'
},
'dataSet3': {
'ID': '3',
'ParentID': '1'
},
'dataSet4': {
'ID': '4',
'ParentID': '3'
}
};
const hashMap = (Object
// 1
.keys(sets)
// 2
.map(datasetKey => ({
originalKey: datasetKey,
id: sets[datasetKey].ID,
parentId: sets[datasetKey].ParentID
}))
// 3
.reduce((hashMap, value) => {
// 4
const hashMapKey = 'hasParentId' + value.parentId;
// 5
if (hashMap[hashMapKey] === undefined) {
hashMap[hashMapKey] = [];
}
// 6
hashMap[hashMapKey].push(value);
// 7
return hashMap;
}, {})
);
{
"hasParentId0": [
{
"originalKey": "dataSet1",
"id": "1",
"parentId": "0"
}
],
"hasParentId1": [
{
"originalKey": "dataSet2",
"id": "2",
"parentId": "1"
},
{
"originalKey": "dataSet3",
"id": "3",
"parentId": "1"
}
],
"hasParentId3": [
{
"originalKey": "dataSet4",
"id": "4",
"parentId": "3"
}
]
}
sets
从对象
Array.prototype.map
获取键数组
Object.keys
将创建数组的每个键从调用
originalKey
映射到新对象。该对象具有3个属性:
id
,
parentId
,
Array.prototype.reduce
Array.prototype.reduce
的第一个参数是带有两个参数的“ reducer”函数。 “ reducer”函数的第一个参数是“累加器”,第二个参数是数组中的项。该reducer将被调用多次,一次调用数组中的每个项目。 reducer函数返回一个累加器,并且该累加器将在此内部函数的下一次调用中使用(因此,数组中的所有项目都将减少到累加器中)。
Array.prototype.reduce
的第二个参数是初始累加器。在这种情况下,初始累加器为空对象
{}
。
hashMapKey
。该字符串将用作累加器的键。
hashMap[hashMapKey]
是一个数组。在这里,我们检查
hashMap[hashMapKey]
的值是否为数组,如果不是,则将其设为一个。
hashMap[hashMapKey]
处有一个数组,我们可以将
value
推入该数组。请记住,
value
是我们从步骤2映射的对象。
hashMap
用作下一个“ reducer”调用的“累加器”。
hashMap
包含正确的变换。下一步需要快速从
sets
转换为
hashMap
。
hashMap
转换为
tier
sets
中的对象,每个边都是通过属性
ParentID
的有向关系。
traverse
遍历此图。
// 1
const tier = {};
let maxDepth = 0;
// 2
function traverse(currentParentId, depth) {
// 3
if (depth > maxDepth) {
maxDepth = depth;
}
// 4
const childrenOfCurrentParent = hashMap['hasParentId' + currentParentId]
// 5
if (childrenOfCurrentParent === undefined) {
return;
}
// 6
childrenOfCurrentParent.forEach(value => {
// 7
const tierKey = 'tier' + depth;
if (tier[tierKey] === undefined) {
tier[tierKey] = [];
}
// 8
tier[tierKey].push(value);
// 9
traverse(value.id, depth + 1);
});
}
currentParentId
:
depth
和
currentParentId
。
currentParentId
是用于标识当前父代ID的密钥。最初使用
0
的
depth
和
0
的
maxDepth
调用此函数。一旦我们看一下代码的实现,这将更有意义。
childrenOfCurrentParent
childrenOfCurrentParent
。明白我们为什么做到了吗?在此表中查找值非常快:)
Array.prototype.forEach
,请不要执行任何操作。
childrenOfCurrentParent
。
value
还是转换中映射对象的
value
。
tierKey
来存储
value
在其中。如果未初始化数组,请对其进行初始化。
value
traverse
函数,以更改
currentParrentId
并递增
depth
。从第3步开始重复,直到没有其他物品可放置为止。简而言之,这基本上是深度优先遍历
tier
转换为
tierArray
maxDepth
的原因。
const sets = {
'dataSet1': {
'ID': '1',
'ParentID': '0'
},
'dataSet2': {
'ID': '2',
'ParentID': '1'
},
'dataSet3': {
'ID': '3',
'ParentID': '1'
},
'dataSet4': {
'ID': '4',
'ParentID': '3'
}
};
// `hashMap` is a data transform
// see the `console.log` of this transform
const hashMap = (Object
// grab the keys of the object `sets`
.keys(sets)
// then map every key to a new object
.map(datasetKey => ({
originalKey: datasetKey,
id: sets[datasetKey].ID,
parentId: sets[datasetKey].ParentID
}))
// reduce the new objects into a single object
.reduce((hashMap, value) => {
// create a key to store the `value`
const hashMapKey = 'hasParentId' + value.parentId;
// if `hashMap[hashMapKey]` isn't intialized yet,
// initialize it to an array
if (hashMap[hashMapKey] === undefined) {
hashMap[hashMapKey] = [];
}
// then push the value (the objects created above)
hashMap[hashMapKey].push(value);
// return the hashMap
return hashMap;
}, {})
);
console.log('hashMap', hashMap);
// create an object to store the `tier`s in.
const tier = {};
// keep track of the `maxDepth` in case you want to transform `tier` to an array
let maxDepth = 0;
// this is a recursive function to traverse your graph
// this implements a depth-first-traversal keeping track of the `depth`
function traverse(currentParentId, depth) {
if (depth > maxDepth) {
maxDepth = depth;
}
const childrenOfCurrentParent = hashMap['hasParentId' + currentParentId]
// if there are no children of the currentParent
if (childrenOfCurrentParent === undefined) {
return;
}
childrenOfCurrentParent.forEach(value => {
const tierKey = 'tier' + depth;
if (tier[tierKey] === undefined) {
tier[tierKey] = [];
}
tier[tierKey].push(value);
traverse(value.id, depth + 1);
});
}
// call the function to start the traversal
// using 0 as the first `currentParentId` and
// using 0 as the first `depth` value
traverse(0, 0);
// the tier object is now created
console.log('tier', tier);
// but it might be more natural to have `tier` as an array
const tierArray = [];
for (let i = 0; i < maxDepth; i += 1) {
tierArray[i] = tier['tier' + i];
}
console.log('tierArray', tierArray);
关于javascript - 使用id和parentid创建层次结构,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44103268/
我正在尝试将新的父项目和新的子项目保存到遗留数据库 我的数据很好,当我保存它时,它同时保存了父项和子项。但是 child 的 SillyNameParentId 始终为 0 我无法更改表结构,所以我必
如何在同一张表上设置父子关系? Id int, title string, ParentId int ---> this is refer to Id 最佳答案 您使用的是什么 ActiveReco
我有以下结构: MyClass { guid ID guid ParentID string Name } 我想创建一个数组,其中包含按照元素应在层次结构中显示的顺序排列的元素(例如,根据
MyClass由 ID 组成ParentID和 List作为Children 我有 MyClass 的列表像这样 ID ParentID 1 0 2 7 3 1 4 5 5 1
我需要一些帮助来构建一个查询,以便我过滤以下数据。 Table: MyTree Id ParentId Visible ===================== 1 null 0
我有一张这样的 table foo(id, parentId) -- there is a FK constraint from parentId to id 我需要删除一个项目及其所有 child
我有一个看似简单的任务,但我遇到的麻烦远比我愿意承认的要多。我有一个层次表,我需要查询和显示由父级和相关子级分组的结果。 我当前的 LINQ 查询: var quests = Questions.In
我有一个看似简单的任务,但我遇到的麻烦远比我愿意承认的要多。我有一个层次表,我需要查询和显示由父级和相关子级分组的结果。 我当前的 LINQ 查询: var quests = Questions.In
网站核心 reference谈谈你可以在Query中使用的一些属性,包括@@templatename、@@id和@@parentid等。 parentid 似乎不起作用 - /sitecore/con
我有以下两个数据库表: 新闻表: newsID, topic, categoryID 类别表: categoryID, title, parentID 我想获取 newsID、主题、主类别的标题,如果
//Set Parent ID for the rest of the Reports data sources this.ReportDataSources.ToList().ForEach(rds
每个父元素都应包含所有子类别的总数。如果解决方案将使用仅 Array 对象方法而不使用 while 循环,那将是非常好的。 这是基础结构的例子: const base = [ { id: 1, c
我会尽量解释清楚。这是我的查询.. SELECT * FROM mm_star_ratings s JOIN mm_posts p ON s.post_id = p.postid WHERE p.ty
我有一个类似 records(ID, ParentID) 的表,其中包含以下数据: ID ParentID 1 null 2 1 3 2 4 2 5 3
我有两个数组。两者都包含具有唯一 id 和 parentid 值的对象(给定的 id 只是示例,实际上它们是由 uuid 生成器生成的)。第一个是按照 parentid 不同于“parent”的对象位
这是表的示例结构: ID Name ParentID ----------------------- 1 Ancestor NULL 2 GrandFather
我有一个具有多层嵌套的层次结构树 JSON。当我尝试循环 JSON 以在 UI 中显示树结构时。我最终得到了循环冗余,因为父 ID 在不同级别上是相同的。我需要为parentID和ID添加唯一标识符,
给定一个平面级别的对象数组,根据 parent 和 id 属性嵌套它们的最有效和现代的方法是什么?顶层对象没有parentId,嵌套层数没有限制。 [{ id: 'OS:MacOS', typ
给定一个平面级别的对象数组,根据 parent 和 id 属性嵌套它们的最有效和现代的方法是什么?顶层对象没有parentId,嵌套层数没有限制。 [{ id: 'OS:MacOS', typ
我正在为我的应用程序编写一个 CMIS 接口(interface)。此接口(interface)返回 cmis:document作为 cmis:folder 的子对象的对象目的。这里是 a part
我是一名优秀的程序员,十分优秀!