数组过滤器没有 return 预期结果
Array filter does not return expected result
我正在尝试过滤 typescript 中的数组我得到了预期的结果,但原始集合被更改了。
private filter(){
this.data = this.originalData.slice().filter((client: Client) => {
// Filter list of orders first
let filteredListOfOrders = client.ListOfOrders.slice().filter((ordersItem: any) => {
const searchStr = JSON.stringify(ordersItem).toLowerCase();
return searchStr.indexOf(this.filterValue.toLowerCase()) !== -1;
});
// Assign filtered list of orders to existing client item
client.ListOfOrders = filteredListOfOrders;
const searchStr = JSON.stringify(client).toLowerCase();
return searchStr.indexOf(this.filterValue.toLowerCase()) !== -1;
});
}
export class Client {
id: number;
name: string;
address: string;
orders: Array<Order>;
}
export class Order {
id: number;
dateOfOrder: Date;
address: string;
}
当我键入地址时,我还想搜索除客户之外的订单项目,return 仅搜索具有过滤地址的客户和具有过滤地址的订单。上面的部分工作但它给我带来了一个问题,因为 this.originalData
被修改并且只设置了与过滤器匹配的订单。 this.originalData
应该保持完整。
有谁知道为什么?认为 slice return 是浅拷贝
嗯,这不适合发表评论,所以我将其扩展为一个答案:
您没有以有意义的方式使用术语 "shallow"。价值观不浅也不深。 副本有浅有深。
对象的浅副本(数组只是一个对象)是一个新对象,其属性包含对非常相同的对象的引用 作为原始对象的属性。如果您修改浅拷贝的其中一个属性的内容,您将在原始对象的类似 属性 中看到该修改,因为这两个属性都指向 非常相同的对象。
如果您希望能够在不触及原始内容的情况下修改副本的内容,则需要执行 深度 复制,在其中递归遍历所有属性每个对象及其所有属性,并制作实际副本。
并不总是需要完整的深拷贝;通常你只关心修改你的数据结构的一部分,你可以将不变的部分保留为浅拷贝。
针对您的具体情况:您正在修改 Client
,方法是将其 orders
数组替换为包含原始内容的某些子集的新数组,并且您没有更改这些内容。所以你真的只需要一个 Client
对象的浅拷贝。你根本不需要 slice()
因为你不关心复制数组(并且 filter()
总是 returns 一个新数组)。你想做这样的事情:
private filter(){
this.data = this.originalData.filter((client: Client) => {
// Filter list of orders first
let filteredListOfOrders = client.ListOfOrders.filter((ordersItem: any) => {
const searchStr = JSON.stringify(ordersItem).toLowerCase();
return searchStr.indexOf(this.filterValue.toLowerCase()) !== -1;
});
const clientCopy = Object.assign({}, client);
// Assign filtered list of orders to copied client item
clientCopy.ListOfOrders = filteredListOfOrders;
const searchStr = JSON.stringify(clientCopy).toLowerCase();
return searchStr.indexOf(this.filterValue.toLowerCase()) !== -1;
});
}
请注意,我这样说 "something like",因为您的代码无法为我编译(complete and verifiable 示例总是有帮助的)。所以你必须调整以上内容以满足你的需要。
希望对您有所帮助;祝你好运!
我正在尝试过滤 typescript 中的数组我得到了预期的结果,但原始集合被更改了。
private filter(){
this.data = this.originalData.slice().filter((client: Client) => {
// Filter list of orders first
let filteredListOfOrders = client.ListOfOrders.slice().filter((ordersItem: any) => {
const searchStr = JSON.stringify(ordersItem).toLowerCase();
return searchStr.indexOf(this.filterValue.toLowerCase()) !== -1;
});
// Assign filtered list of orders to existing client item
client.ListOfOrders = filteredListOfOrders;
const searchStr = JSON.stringify(client).toLowerCase();
return searchStr.indexOf(this.filterValue.toLowerCase()) !== -1;
});
}
export class Client {
id: number;
name: string;
address: string;
orders: Array<Order>;
}
export class Order {
id: number;
dateOfOrder: Date;
address: string;
}
当我键入地址时,我还想搜索除客户之外的订单项目,return 仅搜索具有过滤地址的客户和具有过滤地址的订单。上面的部分工作但它给我带来了一个问题,因为 this.originalData
被修改并且只设置了与过滤器匹配的订单。 this.originalData
应该保持完整。
有谁知道为什么?认为 slice return 是浅拷贝
嗯,这不适合发表评论,所以我将其扩展为一个答案:
您没有以有意义的方式使用术语 "shallow"。价值观不浅也不深。 副本有浅有深。
对象的浅副本(数组只是一个对象)是一个新对象,其属性包含对非常相同的对象的引用 作为原始对象的属性。如果您修改浅拷贝的其中一个属性的内容,您将在原始对象的类似 属性 中看到该修改,因为这两个属性都指向 非常相同的对象。
如果您希望能够在不触及原始内容的情况下修改副本的内容,则需要执行 深度 复制,在其中递归遍历所有属性每个对象及其所有属性,并制作实际副本。
并不总是需要完整的深拷贝;通常你只关心修改你的数据结构的一部分,你可以将不变的部分保留为浅拷贝。
针对您的具体情况:您正在修改 Client
,方法是将其 orders
数组替换为包含原始内容的某些子集的新数组,并且您没有更改这些内容。所以你真的只需要一个 Client
对象的浅拷贝。你根本不需要 slice()
因为你不关心复制数组(并且 filter()
总是 returns 一个新数组)。你想做这样的事情:
private filter(){
this.data = this.originalData.filter((client: Client) => {
// Filter list of orders first
let filteredListOfOrders = client.ListOfOrders.filter((ordersItem: any) => {
const searchStr = JSON.stringify(ordersItem).toLowerCase();
return searchStr.indexOf(this.filterValue.toLowerCase()) !== -1;
});
const clientCopy = Object.assign({}, client);
// Assign filtered list of orders to copied client item
clientCopy.ListOfOrders = filteredListOfOrders;
const searchStr = JSON.stringify(clientCopy).toLowerCase();
return searchStr.indexOf(this.filterValue.toLowerCase()) !== -1;
});
}
请注意,我这样说 "something like",因为您的代码无法为我编译(complete and verifiable 示例总是有帮助的)。所以你必须调整以上内容以满足你的需要。
希望对您有所帮助;祝你好运!