Z
Z
zorro32020-11-10 00:33:12
JavaScript
zorro3, 2020-11-10 00:33:12

How to extract objects from an array into a new object?

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

The problem is in the parent property in the user object, the data is not retrieved by links and is not attached to the 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"
    },
]

Answer the question

In order to leave comments, you need to log in

1 answer(s)
D
Dmitry, 2020-11-10
@zorro3

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) // Результат

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question