How do I extract objects from an array into a new object?
-
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 -
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
1 Answers
Your Answer
To place the code, please use CodePen or similar tool. Thanks you!