如何获取具有嵌套属性的Javascript对象的子集?

4

我正在使用Angular开发,以下是我的Typescript对象数组:

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

我需要获取属性的子集,类似于这样:

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

我该如何实现这个功能呢?我需要创建一个解析器吗,还是有类似Lodash的智能方法可以提取数组的简化版本呢?


请查看map - Aleksey L.
我已经看过了,但是我无法弄清如何映射多个属性:map = array.map(_ => _.x) - smartmouse
只需使用以下代码:const result = docs.map(({ id, type, attachments }) => ({id, type, attachments: attachments.map(a => a.id)})); - Aleksey L.
5个回答

4

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

请看这个。这个完美地运作!

使用相同的映射...如果我只映射文件名等于 example.doc 的附件,怎么办? - smartmouse
1
需要将 attachments.map(({id})=>({id})); 替换为 attachments.filter(att=>att.filename=='example.doc').map(({id})=>({id}));,但请注意如果没有找到匹配项,则现在的附件可能为空。 - Inus Saha

1
你可以使用array.map和对象解构来提取所需属性。
此外,使用JSON.parse和JSON.stringify进行复制并避免副作用。
docs2 = JSON.parse(JSON.stringify(docs)).map(
({id, type, attachements}) => 
  ({ id, 
    type,
    attachements: attachements.map(({id}) => ({id})
  })
)

为什么要使用 JSON.stringify - J. Pichardo
我使用了JSON.stringify来制作对象的深拷贝。否则,如果在原始的“docs”中更改属性(例如“type.id”),则副本中的“type.id”也会更改。 否则,您将不得不手动复制“type”的属性。 两种方法都是有效的解决方案。 - Nova

1
您可以使用带有对象展开的 Array.map,像这样:
const mapSubset = ({ id, type, attachments }) => {
    return { id, type, attachments: attachments.map( {id} => id ) };
};

const subset = docs.map( mapSubset );

0
我正在寻找一种不特定的方法来完成这个或任何类似的情况,到目前为止,我想到了以下几点:
  • 拥有一个IMapping<T>类型,定义了映射每个属性的方式。
  • 拥有一个IMappingFunction<T>接口,确定如何映射特定的事物:

以下代码演示了它:

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

若要查看可运行的代码示例,请点击这里


-2

你需要保留原始数组吗?如果不需要,你可以使用 for 循环遍历对象列表,并使用 'delete' 运算符删除不再需要的属性。

例如:

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

delete Employee.firstname;

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

我看到过 delete 很慢,不太好用...(踩的不是我!) - smartmouse
我可能错了,但我认为这仅适用于您使用delete从数组中删除元素时,而不是从对象中删除属性时。 - Kevin Aud

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接