1

got the following array:

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'
        }
    ]
}]

need to group by 'subs' values to create new array of objects with names of original objects they were into:

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

Whats the best way to do this? Could lodash be of any help

4 Answers 4

1

You could group the data by title and collect 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; }

Sign up to request clarification or add additional context in comments.

Comments

1

Repl Example

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
}, [])

Comments

1

A slightly different approach from the other answers:

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;}

As always, I prefer to encapsulate such transformations into functions. And I prefer not to mutate data any more than necessary. This is likely less efficient than other techniques, but I would go for this simple approach unless testing determined that it was a bottleneck in my application.

Comments

1

A possible solution with lodash:

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

Full example:

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>

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.