0

I have an object I want to unflatten and merge certain subElements by the id of child objects. So that instead of 4 objects with duplicate values, I will only have two, and the two will then have a merged subElement array.

So these my interfaces and test cases:

interface ISubElement {
    id: number;
    price: number;
}

interface IElements {
    id: number;
    subElements: ISubElement[];
}

interface IElementCollection {
    elements: IElements[];
}

const rawObject: IElementCollection = {
    elements: [
        {
            id: 1,
            subElements: [
                {id: 111, price: 500},
            ],
        },
        {
            id: 1,
            subElements: [
                {id: 222, price: 1000},
            ],
        },
        {
            id: 1,
            subElements: [
                {id: 333, price: 1500},
            ],
        },
        {
            id: 2,
            subElements: [
                {id: 123, price: 700},
            ],
        },
    ],
};

const expected: IElementCollection = {
    elements: [
        {
            id: 1,
            subElements: [
                {id: 111, price: 500},
                {id: 222, price: 1000},
                {id: 333, price: 1500},
            ],
        },
        {
            id: 2,
            subElements: [
                {id: 123, price: 700},
            ],
        },
    ],
};

This is the function I came up with:

const mergeSubElements = (rawCollection: IElementCollection) => {
    let mergedCollection: IElementCollection = <IElementCollection> {
        elements: [],
    };

    rawCollection.elements.forEach((element: IElements) => {
        console.log('iterating', JSON.stringify(element, null, 4));
        const existing = mergedCollection.elements.find((existingElement: IElements) => {
            return existingElement.id === element.id;
        });

        if (existing) {
            console.log('should add to existing', JSON.stringify(existing, null, 4));
            existing.subElements.concat(element.subElements);
            return;
        }

        mergedCollection.elements.push(element);
    });

    console.log(JSON.stringify(mergedCollection, null, 4));

    return mergedCollection;
};

It seems my problem is that array.prototype.find only gets me the object as value and not as a reference, as even though I concat fields, they won't be inside the mergedCollecton.

How do I find an object in typescript rather per reference than value?

Here's my mocha test case:

describe('it should merge subElements for each element by id', () => {
    it('this shall merge', () => {

        return expect(mergeSubElements(rawObject)).to.deep.equal(expected);
    });
});
k0pernikus
  • 60,309
  • 67
  • 216
  • 347

1 Answers1

1
existing.subElements = existing.subElements.concat(element.subElements);

It's not that find won't return an object by reference, the issue was with concat:

The concat() method is used to merge two or more arrays. This method does not change the existing arrays, but instead returns a new array.

var arr3 = arr1.concat(arr2);
k0pernikus
  • 60,309
  • 67
  • 216
  • 347