@zorro3

Как извлечь объекты из массива в новый объект?

Функция formattedData извлекает все ссылки c объектов из data.default и data.custom и добавляет к ним id.Также, если пользовательский объект данных совпал с объектом данных по умолчанию по идентификатору, функция создаст parent свойство в пользовательском объекте из объекта данных по умолчанию, а затем удалит совпавший объект по умолчанию из data.default .

Проблема в parent свойстве в пользовательском объекте, данные по ссылкам не извлекаются и не привязываются к id. Помогите пожалуйста реализовать эту логику

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())


Ожидаемый результат

[
    {
        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"
    },
]
  • Вопрос задан
  • 1024 просмотра
Решения вопроса 1
@dimoff66
Кратко о себе: Я есть
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) // Результат
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы