我正在嘗試將一個平面的人員串列轉換為一個結構化的祖先樹。
人員的源陣列如下所示:
const list = [
{
id: 1,
name: 'John',
akin: true,
motherId: undefined,
fatherId: undefined,
partnerIds: [2]
},
{
id: 2,
name: 'Maria',
akin: false,
motherId: undefined,
fatherId: undefined,
partnerIds: [1]
},
{
id: 3,
name: 'Steven',
akin: true,
fatherId: 1,
motherId: 2,
partnerIds: [4, 5]
},
{
id: 4,
name: 'Stella',
akin: false,
motherId: undefined,
fatherId: undefined,
partnerIds: [3]
},
{
id: 5,
name: 'Laura',
akin: false,
motherId: undefined,
fatherId: undefined,
partnerIds: [3]
},
{
id: 5,
name: 'Solomon',
akin: true,
motherId: 4,
fatherId: 3,
partnerIds: []
},
{
id: 6,
name: 'Henry',
akin: true,
fatherId: 3,
motherId: 5,
partnerIds: []
}
]
它可以包含 n 代人,其直系祖先由各自的父親 ID 和母親 ID 定義。未知的父母(已知最古老的祖先,或僅通過伙伴關系相關)只是未定義。伙伴關系由一組 partnerIds 表示。
預期的輸出應如下所示:
const pedigree = [
{
id: 1,
name: 'John',
partnerships: [
{
partner: {
id: 2,
name: 'Maria',
},
children: [
{
id: 3,
name: 'Steven',
partnerships: [
{
partner: {
id: 4,
name: 'Stella',
},
children: [
{
id: 5,
name: 'Solomon'
}
]
},
{
partner: {
id: 5,
name: 'Laura',
},
children: [
{
id: 6,
name: 'Henry',
}
]
}
]
}
]
}
]
}
]
從視覺上看,結果將如下所示: Visual pedigree 所需的輸出格式不是用于存盤,而是用于更輕松的可視化和處理以供以后渲染。
I tried to loop over the flat list, create a hashTable for referencing the single persons and then find partners and common children. My issue is though that my approach only works for two generations, or one level of nesting, although I need it to be suitable for n generations. I think I need some recursive function or way of starting to loop up from the bottom of ancestry somehow, but I can't figure out a smart way.
I'd be glad for any suggestions or tips!
EDIT: This is what I've tried:
const createPedigree = (dataset) => {
const hashTable = Object.create(null)
dataset.forEach(
(person) => (hashTable[person.id] = { ...person, partnerships: [] })
)
const dataTree = []
dataset.forEach((person) => {
if (person.akin) {
if (person.partnerIds.length) {
person.partnerIds.forEach((partnerId) => {
hashTable[person.id].partnerships.push({
partner: { ...dataset.find((p) => p.id === partnerId) },
children: []
})
})
}
}
dataTree.push(hashTable[person.id])
})
dataset.forEach((child) => {
// fill partnerships with children
if (child.fatherId && child.motherId) {
if (
hashTable[child.fatherId].akin &&
hashTable[child.fatherId].partnerships.length
) {
let mother = hashTable[child.fatherId].partnerships.find(
(partnership) => {
return partnership.partner.id === child.motherId
}
)
mother.children.push(child)
} else if (hashTable[child.motherId].akin) {
let father = hashTable[child.motherId].partnerships.find(
(partnership) => {
return partnership.partner.id === child.fatherId
}
)
father.children.push(child)
}
}
})
return dataTree
}
uj5u.com熱心網友回復:
您假設通用解決方案將涉及一些遞回呼叫(或要擴展的候選佇列直到佇列為空)是正確的。
輸出結構級別交替出現:
- 有合伙人的人
- 包含伴侶和孩子的伙伴關系(每個孩子又是 1。)
為了使事情更簡單,我們可以使用 2 個單獨的函式對上面的 2 個步驟進行建模。我選擇了名稱expandPerson和expandPartnership.
const expandPerson = (personId, dataset) => {
// we get the person from the dataset by their id
const personData = dataset.find(p => p.id == personId)
// we clone only the data that we want in the output
const person = { id: personData.id, name: personData.name }
// all partnerIds of this person need to become their parnerships
// so we just map them to an "expanded partnership" (step 2.)
person.partnerships = personData.partnerIds
.map(partnerId => expandPartnership(partnerId, person.id, dataset))
// we return the "expanded" person
return person
}
const expandPartnership = (partner1Id, partner2Id, dataset) => {
// we get the partner from the dataset by their id
const partnerData = dataset.find(p => p.id == partner1Id)
// we clone only the data that we want in the output
const partner = { id: partnerData.id, name: partnerData.name }
// all people in the dataset, whose parents are partner1Id
// and pertner2Id are the children
const children = dataset
.filter(p => p.motherId == partner1Id && p.fatherId == partner2Id
|| p.motherId == partner2Id && p.fatherId == partner1Id)
// we map each child as an "expanded person" again (back to step 1.)
.map(p => expandPerson(p.id, dataset))
// we return the "expanded" partnership
return { partner, children }
}
然后在代碼中呼叫 const pedigree = expandPerson(1, list)
如果根不總是先id: 1找到根id
const rootId = list.find(p => p.akin && !p.fatherId && !p.motherId).id
const pedigree = expandPerson(rootId, list)
注意:您在提供的輸入中有重復的id( id: 5)。你必須解決這個問題。
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/405874.html
標籤:
上一篇:計算嵌套物件和陣列的鍵總數
