javascript - Jämför 2 arrayer med objekt efter 2 olika nycklar. Och skapa ett inbäddat objekt som innehåller förälder och barn


Jag har problem med att jämföra 2 arrayer av objekt. Jag sökte i lodash-dokumentationen, men jag kunde inte hitta någon lämplig metod. Saken är den att jag behöver jämföra objekt med olika nycklar.

private parentArray: {}[] = [
    { Id: 1, Name: 'A' },
    { Id: 2, Name: 'B' },
    { Id: 3, Name: 'C' },
    { Id: 4, Name: 'D' }
  ];

private childArray: {}[] = [
    { Id: 2, parentId: 2, Name: 'a' },
    { Id: 3, parentId: 2, Name: 'b' },
    { Id: 4, parentId: 4, Name: 'c' },
    { Id: 5, parentId: 4, Name: 'd' }
  ];

Jag behöver skapa en ny array av nästlade objekt där 'parentId' kommer att matchas med 'Id' för föräldern vilket kommer att se ut så här:

private newArray = [
    { Id: 1, Name: 'A', Children: [] },
    {
      Id: 2,
      Name: 'B',
      Children: [
        { Id: 2, parentId: 2, Name: 'a' },
        { Id: 3, parentId: 2, Name: 'b' }
      ]
    },
    {
      Id: 3,
      Name: 'C',
      Children: []
    },
    {
      Id: 4,
      Name: 'D',
      Children: [
        { Id: 4, parentId: 4, Name: 'c' },
        { Id: 5, parentId: 4, Name: 'd' }
      ]
    }
  ];

Jag använde '.intersectionWith([arrays], [comparator])' och '.isMatchWith(object, source, [customizer])' men det gav mig inte vad jag behöver. Jag skulle vara tacksam för all hjälp.

Svar #1

Det enklaste sättet att göra detta är förmodligen

const newArray = parentArray.map(
    p => ({ ...p, Children: childArray.filter(c => c.parentId === p.Id) })
)

vilket resulterar i den utgång du letar efter. Observera att detta inte nödvändigtvis är den mest effektiva algoritmen i fallet där parentArray och childArray är stora, eftersom vi loopar över hela childArray för varje element i parentArray (så om childArray är av längden 𝑐 ochit är överordnad av Array och är O(𝑝×𝑐)).

Om sådan prestanda är viktig kan du göra det genom att iterera över varje element i childArray och parentArray en gång (vilket är O(𝑝+𝑐) förutsatt att hash-uppslagningar är O(1)), på detta sätt:

type Parent = typeof parentArray[number];
type Child = typeof childArray[number];
interface New extends Parent {
    Children: Child[];
}

const newArray: New[] = [];
const parentLookup: Record<number, New> = {};    
for (const p of parentArray) {
    const n = { ...p, Children: [] };
    newArray.push(n)
    parentLookup[p.Id] = n;
}
for (const c of childArray) {
    parentLookup[c.parentId]?.Children.push(c);
}
console.log(newArray);

Lekplatslänk till kod

Svar #2

type Parent = {
    Id: number,
    Name: string,
}

type Child = Parent & {
    parentId: number;
}

type ParentAndChildren = {
    Children: Child[]
} & Parent


const parents: Parent[] = [
    { Id: 1, Name: 'A' },
    { Id: 2, Name: 'B' },
    { Id: 3, Name: 'C' },
    { Id: 4, Name: 'D' }
  ];

const children: Child[] = [
    { Id: 2, parentId: 2, Name: 'a' },
    { Id: 3, parentId: 2, Name: 'b' },
    { Id: 4, parentId: 4, Name: 'c' },
    { Id: 5, parentId: 4, Name: 'd' }
  ];

const output = parents.map((p: Parent): ParentAndChildren => {
    return {
        Id: p.Id,
        Name: p.Name,
        Children: children.filter((c) => p.Id === c.parentId),
    }
})

console.log(output);