如果条件匹配,则打字稿数组删除项

时间:2019-05-03 15:26:38

标签: arrays typescript

我有一个带有某些字段的界面,

interface Item {
    id: number;
    name: string;
}

我想实现一种方法removeItemsWithName(items: Item[], name: string),该方法将从给定数组中删除所有具有给定名称的项:

const myItems: Item[] = [
    { id: 1, name: 'foo' },
    { id: 2, name: 'foo' },
    { id: 3, name: 'bar' }
];

removeItemsWithName(myItems, 'foo');
console.log(myItems);

结果应为:

[{id: 3, name: 'bar'}]

在typescript / javascript中是否有可用的方法array.removeIf()(例如Java 8中的Collection.removeIf()),所以我的方法可能类似于以下内容:

function removeItemsWithName(items: Item[], name: string): void {
    items.removeIf(i => i.name === name);
}

我已经找到了问题Remove array element based on object property,但是我需要就地修改原始数组,而不是像创建新的数组那样array.filter()。我还想删除所有符合条件的项目,而不仅仅是第一个。

4 个答案:

答案 0 :(得分:3)

标准解决方案为filter,但这将返回一个 new 数组:

function removeItemsWithName(items: Item[], name: string): Item[] {
  return items.filter(i => i.name !== name);
}

但是,如果您确实需要在适当的位置修改数组,则必须使用如下代码:

function removeItemsWithName(items: Item[], name: string): void {
  let j = 0;
  for (let i = 0; i < items.length; i++) {
    const item = items[i];
    if (item.name !== name) {
        items[j] = item;
        j++;
    }
  }

  items.length = j;
}

或使用splice

function removeItemsWithName(items: Item[], name: string): void {
  for (let i = 0; i < items.length; i++) {
    if (items[i].name === name) {
      items.splice(i--, 1);
    }
  }
}

或者您可以使用类似lodash的库,该库具有便捷的remove方法:

import _remove from 'lodash/remove';

function removeItemsWithName(items: Item[], name: string): void {
  _remove(items, x => x.name === name);
}

答案 1 :(得分:1)

您可以使用Array.prototype.filterhttps://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter):

const myItems = [{
    id: 1,
    name: 'foo'
  },
  {
    id: 2,
    name: 'foo'
  },
  {
    id: 3,
    name: 'bar'
  }
];

console.log(myItems.filter((item) => item.name !== 'foo'))

所以您的功能将仅仅是:

const removeItemsWithName = (items: Item[], name: string): Item[] => items.filter((item: Item) => item.name !== name);

答案 2 :(得分:1)

执行此操作的方法太多,建议使用filter函数。

尝试一下:

function removeItemsWithName(items: Item[], name: string): void {
  items = items.filter(i => i.name !== name);
}

我认为如果removeItemsWithName函数返回一个新数组并且不更改params值会更好。

function removeItemsWithName(items: Item[], name: string): Item[] {
  return items.filter(i => i.name !== name);
}

const myItems: Item[] = [
  { id: 1, name: 'foo' },
  { id: 2, name: 'foo' },
  { id: 3, name: 'bar' }
];

const filtered = removeItemsWithName(myItems, 'foo');
console.log(filtered);

更新

您可以使用Collection方法创建所有者removeIf

interface Item {
  id: number;
  name: string;
}

class MyCollection<T> {
  private items: Array<T>;

  constructor(init?: T[]) {
    this.items = init || [];
  }

  get(): T[] {
    return this.items;
  }

  removeIf(conditionFunction: (i: T) => boolean) {
    this.items = this.items.filter(i => !conditionFunction(i));
  }
}

const myItems: MyCollection<Item> = new MyCollection<Item>([
  { id: 1, name: "foo" },
  { id: 2, name: "foo" },
  { id: 3, name: "bar" }
]);

function removeItemsWithName<T extends Item>(
  items: MyCollection<T>,
  name: string
): void {
  items.removeIf(i => i.name === name);
}

removeItemsWithName(myItems, "foo");
console.log(myItems.get());

答案 3 :(得分:1)

采取一项,利用.filter()。更少的代码,但是O(2n)。

function removeItemsWithName(items: Item[], name: string): void {
  var newArray = items.filter(i => i.name !== name);
  items.length = 0; // this empty the original array
  newArray.forEach(item => { items.push(item) });
}

取两个,使用旧的O(n)方式.splice()

function removeItemsWithName(items: Item[], name: string): void {
  var index = items.length - 1;
  var predicate = i => i.name === name;
  while(index >= 0) {
    if (predicate(items[index])) {
      items.splice(index, 1)
    }
    index--;
  }
}