Создание объектов из свойств объектов - PullRequest
1 голос
/ 26 февраля 2020

получил следующий массив:

const myObjects = [{
    id: '1',
    name: 'name1',
    subs: [
        {
            id: '1',
            title: 'subName1'
        },
        {
            id: '2',
            title: 'subName2'
        }
    ]
},
{
    id: '2',
    name: 'name2',
    subs: [
        {
            id: '2',
            title: 'subName2'
        },
        {
            id: '3',
            title: 'subName3'
        }
    ]
}]

необходимо сгруппировать по значениям 'subs', чтобы создать новый массив объектов с именами исходных объектов, в которые они входили:

const mySubs = [
    {
        title: 'subName1',
        objects: ['name1']
    },
    {
        title: 'subName2',
        objects: ['name1', 'name1']
    },
    {
        title: 'subName3',
        objects: ['name2']
    }
]

Что лучший способ сделать это? Может ли loda sh быть полезным

Ответы [ 4 ]

1 голос
/ 26 февраля 2020

Возможное решение с loda sh:

_.chain(myObjects)
  .map(myObject =>
    myObject.subs.map(sub => ({ object: myObject.name, title: sub.title })),
  )
  .flatten()
  .groupBy('title')
  .map((data, title) => ({ title, objects: _.map(data, 'object') }))
  .value()

Полный пример:

const myObjects = [{
    id: '1',
    name: 'name1',
    subs: [
        {
            id: '1',
            title: 'subName1'
        },
        {
            id: '2',
            title: 'subName2'
        }
    ]
},
{
    id: '2',
    name: 'name2',
    subs: [
        {
            id: '2',
            title: 'subName2'
        },
        {
            id: '3',
            title: 'subName3'
        }
    ]
}]

const result = _.chain(myObjects)
  .map(myObject =>
    myObject.subs.map(sub => ({ object: myObject.name, title: sub.title })),
  )
  .flatten()
  .groupBy('title')
  .map((data, title) => ({ title, objects: _.map(data, 'object') }))
  .value()
  
console.log(result)
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.15/lodash.min.js"></script>
1 голос
/ 26 февраля 2020

Пример Repl

let mySubs = myObjects.reduce((_mySubs = [], myObjectValue) => {
  myObjectValue.subs.forEach((sub) => {
    let mySub = _mySubs.find((myObject) => myObject.title === sub.title)
    if(!mySub) {
      mySub = {
        title: sub.title,
        objects: [],
      }
      _mySubs.push(mySub)
    }
    mySub.objects.push(myObjectValue.name)
  })
  return _mySubs
}, [])
1 голос
/ 26 февраля 2020

Немного отличается от других ответов:

const extractSubs = myObjects => 
  Object .values (myObjects .reduce (
    (a, {name, subs}) => subs .reduce (
      (a, {title}) => ({... a, [title]: {title, objects: [...((a [title] && a[title].objects) || []), name]}}),
      a
    ),
    {}
  ))

const myObjects = [{id: '1', name: 'name1', subs: [{id: '1', title: 'subName1'}, {id: '2', title: 'subName2'}]}, {id: '2', name: 'name2', subs: [{id: '2', title: 'subName2'}, {id: '3', title: 'subName3'}]}]

console .log (extractSubs (myObjects))
.as-console-wrapper {max-height: 100% !important; top: 0;}

Как всегда, я предпочитаю заключать такие преобразования в функции. И я предпочитаю не изменять данные больше, чем необходимо. Это, вероятно, менее эффективно, чем другие методы, но я бы остановился на этом простом подходе, если только тестирование не определило, что это было узким местом в моем приложении.

1 голос
/ 26 февраля 2020

Вы можете сгруппировать данные по title и собрать name.

const
    objects = [{ id: '1', name: 'name1', subs: [{ id: '1', title: 'subName1' }, { id: '2', title: 'subName2' }] }, { id: '2', name: 'name2', subs: [{ id: '2', title: 'subName2' }, { id: '3', title: 'subName3' }] }],
    subs = Object.values(objects.reduce((r, { name, subs }) => {
        subs.forEach(({ title }) => {
            r[title] = r[title] || { title, objects: [] };
            r[title].objects.push(name);
        });
        return r;
    }, {}));

console.log(subs);
.as-console-wrapper { max-height: 100% !important; top: 0; }
...