过滤器未创建新数组?

兰威尔

我的以下代码有问题,也许我只是不了解过滤器的工作原理。根据我的理解,过滤器应该返回一个新数组。filteredItems是我在DOM中对* ngFor所做的事情。因此,我首先使用slice方法将输入项数组进行浅表复制到我的filteredItems和copyItems中。之后,我尝试从浅复制项数组中返回一个新的过滤项数组。但是,每当我尝试过滤项目数组时,它实际上都会处理原始数组的数据,而不是仅仅返回一个包含我所需数据的新数组。

@Input() private items: Items[];

private copyItems = new Array<Items>();

public input = new FormControl();
public filteredItems = new Array<Items>();

ngOnInit() {
  this.filteredItems = this.items.slice();
  this.copyItems = this.items.slice();

  this.subscription = this.input.valueChanges
    .debounceTime(500)
    .distinctUntilChanged()
    .map((value) => {
      return value;
    })
    .subscribe((searchTerm) => {
      if (searchTerm) {
        this.filteredItems = this.filterItems(searchTerm.toLowerCase());
        console.log(this.items);
      } else {
        this.copyItems = this.items.slice();
        this.filteredItems = this.items.slice();
      }
    });
}

private filterItems(searchTerm: string): Array<Items> {
  return this.copyItems.filter((item) => {
    let filterExists: boolean = false;
    let itemName = <string>item.name;
    if (itemName.toLowerCase().startsWith(searchTerm)) {
      filterExists = true;
    }

    let filteredChildren =  this.filterChildren(searchTerm, item);

    if (filteredChildren.length > 0) {
      filterExists = true;
      item.children = filteredChildren;
    }

    if (filterExists)
      return true;
    else
      return false;
  });
}

private filterChildren(searchTerm: string, item: Items): Array<ChildItems> {
  return item.children.filter(child => {
    let childName = <string>child.name;
    if (childName.toLowerCase().startsWith(searchTerm)) {
      return child;
    }
  });
}

有人可以告诉我我在这里做错了什么吗。在过去的两天里,我反复地将自己的头撞在桌子上,无法解决此问题。

提前致谢!

TJ人群

filter 的确确实创建了一个新数组,但是原始对象中引用的对象也被新数组引用,因此对它们的更改可以通过两者看到。

如果要更改数组中某个项目的状态,并且不希望通过旧数组看到该更改,则需要创建一个项目并在数组中使用它。那将map不是filter -或更确切地说,这是两者的结合。

这是您当前正在做的一个简单示例;请注意,无论我们在哪个数组中查看它,如何state变得2

var original = [
  {id: 1, state: 1},
  {id: 2, state: 1},
  {id: 3, state: 1}
];
var filtered = original.filter(item => {
  if (item.id % 2 == 1) {
    ++item.state;
    return item;
  }
});
console.log("original", original);
console.log("filtered", filtered);
.as-console-wrapper {
  max-height: 100% !important;
}

坚持使用现有Array.prototype功能,您进行变异过滤的方法是先使用map然后filter删除undefined条目:

var original = [
  {id: 1, state: 1},
  {id: 2, state: 1},
  {id: 3, state: 1}
];
var filtered = original
  .map(item => {
    if (item.id % 2 == 1) {
      return {id: item.id, state: item.state + 1};
    }
  })
  .filter(item => !!item);
console.log("original", original);
console.log("filtered", filtered);
.as-console-wrapper {
  max-height: 100% !important;
}

或者,您可以给自己一个mapFilter函数:

Object.defineProperty(Array.prototype, "mapFilter", {
  value: function(callback, thisArg) {
    var rv = [];
    this.forEach(function(value, index, arr) {
      var newValue = callback.call(thisArg, value, index, arr);
      if (newValue) {
        rv.push(newValue);
      }
    })
    return rv;
  }
});
var original = [
  {id: 1, state: 1},
  {id: 2, state: 1},
  {id: 3, state: 1}
];
var filtered = original
  .mapFilter(item => {
    if (item.id % 2 == 1) {
      return {id: item.id, state: item.state + 1};
    }
  });
console.log("original", original);
console.log("filtered", filtered);
.as-console-wrapper {
  max-height: 100% !important;
}

...但是所有有关扩展内置原型的警告都适用(您可以将其传递给数组使用的实用程序)。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章