How do I extract objects from an array into a new object?

  • 0
    The formattedData function extracts all object references from data.default and data.custom and adds id to them. Also, if the custom data object matches a default data object by ID, the function will create a parent property on the custom object from the default data object, and then remove the matched default data object from the data.default .

    The problem is in the parent property in the custom object, the data on the links is not retrieved and not bound to id. Please help me implement this logic.

    const data = {
        default: [
            {
                id: "first",
                links: [{
                    name: "testName1",
                    number: 1
                }]
            },
            {
                id: "second",
                links: [
                    {
                        name: "testName2",
                        number: 2
                    },
                    {
                        name: "testName2.1",
                        number: 2.1
                    }
                ]
            },
            {
                id: "third",
                links: [
                    {
                        name: "testName3",
                        number: 3
                    },
                    {
                        name: "testName3.1",
                        number: 3.1
                    },
                ]
            },
        ],
        custom: [
            {
                id: "first",
                links: [{
                    name: "testName1",
                    number: 1
                }]
            },
            {
                id: "second",
                links: [
                    {
                        name: "testName2",
                        number: 2
                    },
                    {
                        name: "testName2.1",
                        number: 2.1
                    }
                ]
            },
        ]
    }
    
    function formattedData() {
        let defaultData = data.default || []
        let customData = data.custom || []
        const extractDefaultDataId = defaultData.map(el => el.id)
        const extractCustomDataId = customData.map(el => el.id)
            //  create parent object from default data object
            //  if custom data object have matched to default data object by id
            customData = customData.map((cd) => {
                const parent = defaultData
                    .find(dd => dd.id === cd.id)
                return {
                    ...cd,
                    ...(extractDefaultDataId
                        .includes(cd.id)) && {
                        parent: {
                            ...parent,
                            scope: "defaultData"
                        }
                    },
                }
            })
            // remove default object from "default" property
            // if custom data object have matched to default data object by id
            defaultData = defaultData.filter(
                dd => !extractCustomDataId.includes(dd.id)
            )
        // extracting all links which default and custom data has
        // and linking them to id
        return Object.entries({ defaultData, customData })
            .map(([k, v]) => v.map(({ links, ...link }) => links
                .map(el => ({
                    ...el,
                    ...link,
                    scope: `${k}`,
                }))))
            .flat(2)
    }
    
    console.log(formattedData())


    Expected result

    [
        {
            name: "testName3",
            number: 3,
            id: "third",
            scope: "defaultData"
        },
        {
            name: "testName3.1",
            number: 3.1,
            id: "third",
            scope: "defaultData"
        },
    
        {
            name: "testName1",
            number: 1,
            id: "first",
            parent: {
                id: "first",
                name: "testName1",
                number: 1,
                scope: "defaultData"
            },
            scope: "customData"
        },
        {
            name: "testName2",
            number: 2,
            id: "second",
            parent: {
                id: "second",
                name: "testName2",
                number: 2,
                scope: "defaultData"
            },
            scope: "customData"
        },
        {
            name: "testName2.1",
            number: 2.1,
            id: "second",
            parent: {
                id: "second",
                name: "testName2.1",
                number: 2.1,
                scope: "defaultData"
            },
            scope: "customData"
        },
    ]
    JavaScript Micah Rojas, Oct 7, 2019

  • 1 Answers
  • 0
    let customKeys 
    const items = Array.from(['custom', 'default']).flatMap(group => {
    const scope = group + "Data"

    // Собираем элементы группы
    const items = (data[group] || []).flatMap(({ id, links }) =>
    links.map(link => ({...link, id, scope }))
    )

    const getKey = v => JSON.stringify([v.id, v.number])

    if (!customKeys) {
    // индексируем ключи кастомных элементов
    customKeys = items.reduce((agg, v) =>
    Object.assign(agg, {[getKey(v)]: v})
    , {})

    return items
    } else {
    // Для ключей, найденных ранее, устанавливаем родителя и отфильтровываем
    const defaultIds = []
    const defaultItems = items.filter(v => {
    const child = customKeys[getKey(v)]
    if (child) {
    child.parent = v
    defaultIds.push(v.id)
    } else {
    return true
    }
    })

    // Оставляем в data.default лишь элементы с id, не найденные в custom
    if (defaultIds.length) {
    const idsSet = new Set(defaultIds)
    const copy = [...data.default]
    data.default.length = 0
    data.default.push(...copy.filter(v => !idsSet.has(v.id)))
    }

    return defaultItems
    }
    })

    console.log(data) // Дата без кастомных ключей в дефолт скоуп
    console.log(items) // Результат
    Anonymous

Your Answer
To place the code, please use CodePen or similar tool. Thanks you!