smartmouse
smartmouse

Reputation: 14404

How to get a subset of a Javascript object with nested properties?

I'm developing with Angular and I have the following Typescript array of objects:

docs = [
    { 
        id: '1',
        type: {
            id: 1
            desc: 'Category 1',
        }
        title: 'Foo",
        date: '2018-06-21',
        attachments: [
            { id: 51, filename: 'foo.pdf', title: 'Foo' },
            { id: 20, filename: 'bar.doc', title: 'Bar' }
        ]
    },
    { 
        id: '2',
        type: {
            id: 2
            desc: 'Category 2',
        }
        title: 'Bar",
        date: '2018-06-21',
        attachments: [
            { id: 15, filename: 'foobar.xls', title: 'Foobar' },
            { id: 201, filename: 'example.doc', title: 'Example' }
        ]
    }
]

I need to get only a subset of the properties, something like this:

docs = [
    { 
        id: '1',
        type: {
            id: 1
            desc: 'Category 1',
        }
        attachments: [
            { id: 51 },
            { id: 20 }
        ]
    },
    { 
        id: '2',
        type: {
            id: 2
            desc: 'Category 2',
        }
        attachments: [
            { id: 15 },
            { id: 201 }
        ]
    }
]

How can I achieve this? Have I to create a parser or does exist any smart way (such as Lodash) to extract a lite version of the array?

Upvotes: 4

Views: 4616

Answers (5)

Inus Saha
Inus Saha

Reputation: 1918

var docs = [{"id":"1","type":{"id":1,"desc":"Category 1"},"title":"Foo","date":"2018-06-21","attachments":[{"id":51,"filename":"foo.pdf","title":"Foo"},{"id":20,"filename":"bar.doc","title":"Bar"}]},{"id":"2","type":{"id":2,"desc":"Category 2"},"title":"Bar","date":"2018-06-21","attachments":[{"id":15,"filename":"foobar.xls","title":"Foobar"},{"id":201,"filename":"example.doc","title":"Example"}]}];

const result = docs.map(({id,type,attachments})=>{
    let doc={id,type};
    doc.attachments=attachments.map(({id})=>({id}));
    return doc;
});

console.log(result);

have a look at this. this works perfectly!

Upvotes: 4

J. Pichardo
J. Pichardo

Reputation: 3115

I was looking for a non-specific way to accomplish this or any other similar cases, so far I've thought of the following:

  • Have an IMapping<T> type, that defines the way to map each property.
  • Have an IMappingFunction<T> interface, that determines how to map a specific thing:

The following code demonstrates it:

type IMapping<T> = {
    [P in keyof T]: IMapping<T[P]> | IMappingFunction<T[P]>;
}

interface IMappingFunction<T>{
    (t: T): T | Partial<T>
}

class Person{
    name: string;
    lastName: string;
}

const obj: IMapping<Person> =  {
    name: s => s.toUpperCase(),
    lastName: s => s
}

function map<T>(obj: T, mapping: IMapping<T>) {
    return Object.keys(obj)
        .map(prop => { 
            const propMapping = mapping[prop];

            return {
                key: prop,
                value: typeof propMapping === 'function' ?
                    propMapping(obj[prop]) :
                    map(obj, propMapping)
            };
        })
        .reduce((acc, prop) => ({...acc, [prop.key]: prop.value}), { });
}

console.log(map({ name: 'Name', lastName: 'LastName'}, obj));

For a runnable snippet check here

Upvotes: 0

Dimitri Lavren&#252;k
Dimitri Lavren&#252;k

Reputation: 4879

You can use Array.map with object spreading, something like this:

const mapSubset = ({ id, type, attachments }) => {
    return { id, type, attachments: attachments.map( {id} => id ) };
};

const subset = docs.map( mapSubset );

Upvotes: 1

Nova
Nova

Reputation: 11

You can use array.map and object destructuring to extract only the wanted properties.

Also use JSON.parse and JSON.stringify to make a copy and avoid side effetcs.

docs2 = JSON.parse(JSON.stringify(docs)).map(
({id, type, attachements}) => 
  ({ id, 
    type,
    attachements: attachements.map(({id}) => ({id})
  })
)

Upvotes: 1

Kevin Aud
Kevin Aud

Reputation: 398

do you need to leave the original array intact? If not you can iterate through the list of objects using a for loop and use the 'delete' operator to delete the properties you no longer want.

For example:

var Employee = {
  firstname: "Mohammed",
  lastname: "Haddad"
}

delete Employee.firstname;

console.log(Employee);
// expected output: { lastname: "Haddad" }

Upvotes: -2

Related Questions