英文:
Derive parent-child hierarchy from an array using DataWeave (additional details)
问题
这是对先前问题的跟进。感谢@harshank的快速帮助。我将此问题单独发布,因为需要额外的检查,这在先前的问题中我没有提到。因此,先前发布的解决方案适用于所述要求。
我在此添加了额外的要求:
-
决定
gp
和parent
是否匹配取决于额外的属性eye_colour
(请参见下面的示例有效负载)。 -
在响应中还需要填充额外的字段(在先前的问题中没有提到)。像
name
和eye_colour
之类的东西。
所以,例如,这是有效负载:
[
{
"gp": "T1",
"gp_eye_colour": "blue",
"gp_name" : "John",
"parent": "T1",
"parent_eye_colour" : "black",
"parent_name" : "Sam",
"child": "C1",
"child_eye_colour" : "brown",
"child_name" : "C1"
},
{
"gp": "T1",
"gp_eye_colour": "blue",
"gp_name" : "John",
"parent": "T1",
"parent_eye_colour" : "black",
"parent_name" : "Sam",
"child": "C1",
"child_eye_colour" : "brown",
"child_name" : "C1"
}
]
现在,使用先前的解决方案,我尝试构建如下:
%dw 2.0
output application/xml
// 层次结构的结构。比如,如果你添加了一个"grand child",它应该能够工作(尽管我还没有测试过这一点)
var hierarchy = {
gp: {
parent: {
child: null
}
}
}
fun getDirectGeanologies(records, hierarchyStructure,isGp,isParent,isChild) = do {
var topLevel = keysOf(hierarchyStructure)[0] as String
var secondLevel = keysOf(hierarchyStructure[topLevel])[0]
---
(records groupBy $[topLevel])
mapObject ((level1Childs, code) ->
genealogy: {
code: code,
eye_colour: if(isGp) (level1Childs.gp_eye_colour) else if(isParent) (level1Childs.parent_eye_colour) else (level1Childs.child_eye_colour),
name: if(isGp) (level1Childs.gp_name) else if(isParent) (level1Childs.parent_name) else (level1Childs.child_name),
hierarchy:
if(secondLevel != null) // 如果没有更多的子元素,什么也不做。
(level1Childs groupBy ((item) -> item[secondLevel] ~= code) // 这是为了处理当parent = gp的情况
mapObject ((value, hasSameParent) ->
// 如果parent = gp,我们希望跳过parent,直接链接到child
if(hasSameParent as Boolean) getDirectGeanologies(value, hierarchyStructure[topLevel][secondLevel],false,false,true)
// 递归调用带有子记录的函数,并沿着hierarchyStructure向下移动一个级别
else getDirectGeanologies(value, hierarchyStructure[topLevel],false,true,false)
))
else {}
}
)
}
---
list: getDirectGeanologies(payload,hierarchy,true,false,false)
然而,它会生成重复的eye_colour
和name
元素。理想情况下,它应该只打印值一次,值应该是gp / parent / child中的一个。
这是期望的响应:
<?xml version='1.0' encoding='UTF-8'?>
<list>
<genealogy>
<code>T1</code>
<eye_colour>blue</eye_colour>
<name>John</name>
<hierarchy>
<genealogy>
<code>C1</code>
<eye_colour>brown</eye_colour>
<name>C1</name>
<hierarchy/>
</genealogy>
</hierarchy>
</genealogy>
</list>
我还没有弄清如何检查gp和parent是否基于两个字段(gp & gp_eye_colour
与parent & parent_eye_colour
)具有相同的值。
感谢@sudhish_s的回复,我添加了一个示例,详细说明了何时跳过parent(当gp和parent的gp & gp_eye_colour
相同时)。
示例输入:(这里,parent "Sam" 不应被跳过,因为尽管gp和parent相同,但他们的眼睛颜色不同。类似地,在"Don"的情况下,应该跳过此parent,因为gp和parent及其眼睛颜色都相同)。
[
{
"gp": "T1",
"gp_eye_colour": "blue",
"gp_name" : "John",
"parent": "T1",
"parent_eye_colour" : "black",
"parent_name" : "Sam",
"child": "C1",
"child_eye_colour" : "brown",
"child_name" : "C1"
},
{
"gp": "T1",
"gp_eye_colour": "blue",
"gp_name" : "John",
"parent": "T1",
"parent_eye_colour" : "blue",
"parent_name" : "Don",
"child": "C1",
"child_eye_colour" : "brown",
"child_name" : "C1"
}
]
这是期望的响应:
<?xml version='1.0' encoding='UTF-8'?>
<list>
<genealogy>
<code>T1</code>
<eye_colour>blue</eye_colour>
<name>John</name>
<hierarchy>
<genealogy>
<code>T1</code>
<eye_colour>black</eye_colour>
<name>Sam</name>
<hierarchy>
<genealogy>
<code>C1</code>
<eye_colour>brown</eye_colour>
<name>C1</name>
<hierarchy/>
</genealogy>
</hierarchy>
</genealogy>
<details>
<summary>英文:</summary>
This is a follow up to an [earlier][1] question. Thanks @harshank for the quick help. I am posting this question separately since there was an additional check required which I had not asked in the earlier question. So, the solution posted earlier works fine for the stated requirement.
I am adding the additional requirement here:
1. The decision if ```gp``` and ```parent``` match depends on an additional attribute ```eye_colour``` (please see sample payload below).
2. Also in the response additional fields need to be populated (which was not mentioned in the earlier question). Things like ```name``` and ```eye_colour```.
So, as an example this is the payload:
```json
[
{
"gp": "T1",
"gp_eye_colour": "blue",
"gp_name" : "John",
"parent": "T1",
"parent_eye_colour" : "black",
"parent_name" : "Sam",
"child": "C1",
"child_eye_colour" : "brown",
"child_name" : "C1"
},
{
"gp": "T1",
"gp_eye_colour": "blue",
"gp_name" : "John",
"parent": "T1",
"parent_eye_colour" : "black",
"parent_name" : "Sam",
"child": "C1",
"child_eye_colour" : "brown",
"child_name" : "C1"
}
]
And now using the earlier solution, I have tried to build on top of it as:
%dw 2.0
output application/xml
// hierarchy's structure. If, lets say you add a "grand child" it should work. (haven't tested this though)
var hierarchy = {
gp: {
parent: {
child: null
}
}
}
fun getDirectGeanologies(records, hierarchyStructure,isGp,isParent,isChild) = do {
var topLevel = keysOf(hierarchyStructure)[0] as String
var secondLevel = keysOf(hierarchyStructure[topLevel])[0]
---
(records groupBy $[topLevel])
mapObject ((level1Childs, code) ->
genealogy: {
code: code,
eye_colour: if(isGp) (level1Childs.gp_eye_colour) else if(isParent) (level1Childs.parent_eye_colour) else (level1Childs.child_eye_colour),
name: if(isGp) (level1Childs.gp_name) else if(isParent) (level1Childs.parent_name) else (level1Childs.child_name),
hierarchy:
if(secondLevel != null) // If there are no more childs, do nothing.
(level1Childs groupBy ((item) -> item[secondLevel] ~= code) // This is to handle when parent = gp
mapObject ((value, hasSameParent) ->
// If parent = gp, we want to skip parent and link directly to child
if(hasSameParent as Boolean) getDirectGeanologies(value, hierarchyStructure[topLevel][secondLevel],false,false,true)
// recurrsively call the function with child records and going down the hierarchyStructure by one
else getDirectGeanologies(value, hierarchyStructure[topLevel],false,true,false)
))
else {}
}
)
}
---
list: getDirectGeanologies(payload,hierarchy,true,false,false)
However, it is generating duplicate elements for eye_colour
and name
. Ideally, it should print the values only once with the value of either gp / parent / child.
This is the expected response:
<?xml version='1.0' encoding='UTF-8'?>
<list>
<genealogy>
<code>T1</code>
<eye_colour>blue</eye_colour>
<name>John</name>
<hierarchy>
<genealogy>
<code>C1</code>
<eye_colour>brown</eye_colour>
<name>C1</name>
<hierarchy/>
</genealogy>
</hierarchy>
</genealogy>
</list>
I was also not able to figure out how to check if gp and parent have same values based on two fields (gp & gp_eye_colour
vs parent & parent_eye_colour
)
Thank you @sudhish_s for the response, adding an example to elaborate regarding decision of when to skip parent (when gp & gp_eye_colour
of gp are same as parent & parent_eye_colour
of parent).
Sample input: (Here parent Sam
should not be skipped since though gp and parent are same their eye colours are different. Similarly, in case of Don
, this parent should be skipped since gp and parent and their eye colours are the same).
[
{
"gp": "T1",
"gp_eye_colour": "blue",
"gp_name" : "John",
"parent": "T1",
"parent_eye_colour" : "black",
"parent_name" : "Sam",
"child": "C1",
"child_eye_colour" : "brown",
"child_name" : "C1"
},
{
"gp": "T1",
"gp_eye_colour": "blue",
"gp_name" : "John",
"parent": "T1",
"parent_eye_colour" : "blue",
"parent_name" : "Don",
"child": "C1",
"child_eye_colour" : "brown",
"child_name" : "C1"
}
]
Here is the expected response:
<?xml version='1.0' encoding='UTF-8'?>
<list>
<genealogy>
<code>T1</code>
<eye_colour>blue</eye_colour>
<name>John</name>
<hierarchy>
<genealogy>
<code>T1</code>
<eye_colour>black</eye_colour>
<name>Sam</name>
<hierarchy>
<genealogy>
<code>C1</code>
<eye_colour>brown</eye_colour>
<name>C1</name>
<hierarchy/>
</genealogy>
</hierarchy>
</genealogy>
<genealogy>
<code>C1</code>
<eye_colour>brown</eye_colour>
<name>C1</name>
<hierarchy/>
</genealogy>
</hierarchy>
</genealogy>
</list>
答案1
得分: 1
以下是您要翻译的部分:
Slightly different version. Used arrays for reference.
%dw 2.0
output application/xml
var hierarchy = ["gp", "parent", "child"]
fun getDirectGeanologies(records, level) = do {
var hLevel = hierarchy[level]
---
records groupBy $[hLevel] mapObject ((children, code) ->
genealogy: {
code: code,
eye_colour: children[0][hLevel ++ "eye_colour"],
name: children[0][hLevel ++ "name"],
hierarchy:
if (level == sizeOf(hierarchy) - 1) {}
else do {
var nextLevel = level + 1
var nextGen = children groupBy ($[hierarchy[nextLevel]])
---
nextGen mapObject ((nextGenChildren, nextGenCode) ->
if (nextGenCode == code)
getDirectGeanologies (nextGenChildren, nextLevel + 1 )
else
getDirectGeanologies (nextGenChildren, nextLevel)
)
}
}
)
}
---
list: getDirectGeanologies(payload,0)
The issue with elements appear multiple times is due to the level1Childs
is Array. Change the output to json
, it will be more clear. If you want to use your code, change the eye_colour
and name
mapping to below
eye_colour: if(isGp) (level1Childs[0].gp_eye_colour) else if(isParent) (level1Childs[0].parent_eye_colour) else (level1Childs[0].child_eye_colour),
name: if(isGp) (level1Childs[0].gp_name) else if(isParent) (level1Childs[0].parent_name) else (level1Childs[0].child_name),
英文:
Slightly different version. Used arrays for reference.
%dw 2.0
output application/xml
var hierarchy = ["gp", "parent", "child"]
fun getDirectGeanologies(records, level) = do {
var hLevel = hierarchy[level]
---
records groupBy $[hLevel] mapObject ((children, code) ->
genealogy: {
code: code,
eye_colour: children[0][hLevel ++ "_eye_colour"],
name: children[0][hLevel ++ "_name"],
hierarchy:
if (level == sizeOf(hierarchy) - 1) {}
else do {
var nextLevel = level + 1
var nextGen = children groupBy ($[hierarchy[nextLevel]])
---
nextGen mapObject ((nextGenChildren, nextGenCode) ->
if (nextGenCode == code)
getDirectGeanologies (nextGenChildren, nextLevel + 1 )
else
getDirectGeanologies (nextGenChildren, nextLevel)
)
}
}
)
}
---
list: getDirectGeanologies(payload,0)
The issue with elements appear multiple times is due to the level1Childs
is Array. Change the output to json
, it will be more clear. If you want to use your code, change the eye_colour
and name
mapping to below
eye_colour: if(isGp) (level1Childs[0].gp_eye_colour) else if(isParent) (level1Childs[0].parent_eye_colour) else (level1Childs[0].child_eye_colour),
name: if(isGp) (level1Childs[0].gp_name) else if(isParent) (level1Childs[0].parent_name) else (level1Childs[0].child_name),
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论