65.9K
CodeProject 正在变化。 阅读更多。
Home

TypeScript 100天 (第7天)

starIconstarIconstarIconstarIconstarIcon

5.00/5 (1投票)

2022 年 2 月 17 日

CPOL

7分钟阅读

viewsIcon

3770

什么是数组以及如何使用它来管理多个项目

首先,我想为推迟这篇博文表示歉意。发生了很多事情阻碍了我,但我并没有忘记写这个系列。在 第 6 天,我们学习了如何使用继承和抽象类来展示我们如何对“对象”进行建模。在这篇博文中,我们将开始研究如何使用数组来管理多个项。

什么是数组?

我们可以将数组视为一种便捷的方式来创建一组“事物”,方便我们进行操作。回到我之前的乐器示例,我们可以将吉他上的弦视为“弦”的集合(这里是乐器弦,而不是文本字符串)。在吉他上,每根弦的宽度都不同,取决于该弦的调音有多高。现在,如果我们想在代码中引用它们,我们可以选择创建单独的变量,例如 string1string2 等等。这在使用时会变得非常麻烦,并且当我们有 7 弦、8 弦甚至 12 弦的吉他时会限制我们。

有了数组,我们只需要一个数组,然后将单个 string 添加进去即可。

声明数组

我们可以用多种不同的方式创建数组。如果我们预先知道数组的内容,那么创建和填充数组的简单方法是这样的。

const strings: number[] = [10, 13, 17, 26, 36, 46];

我在这里指定了类型,但这并非绝对必要。我们可以省略 number[] 部分,它仍然会创建一个数字数组,如下所示:

const strings = [10, 13, 17, 26, 36, 46];

TypeScript 很聪明,知道这是一个数字数组,因此不允许我们将不同类型添加到此数组中。

现在,我确实提到了还有其他声明数组的方法。TypeScript 还为我们提供了使用一种称为泛型类型来创建数组的能力。目前不用担心泛型是什么,我们将在本系列的后面部分更详细地介绍泛型。总之,声明同一个已填充数组的另一种方法如下所示。

const genericString: Array<number> = [10, 13, 17, 26, 36, 46];

Array<number> 是数组的泛型类型,在功能上与上面原始的数组声明完全相同。

声明空数组

我们并不总是知道要将什么放入数组中。在很多情况下,我们希望在声明数组后向其中添加项。如果我们使用 [] 语法来表示数组,那么我们会这样声明我们的数组:

const emptyStrings: number[] = [];

如果我们想使用 Array<> 语法,我们有两个选择。第一个选择是使用。

const emptyGenericStrings: Array<number> = [];

或者,因为这是一种类型,我们可以像这样使用 new() 语法:

const emptyGenericStrings2: Array<number> = new Array<number>();

向我们的数组添加元素

显然,当我们创建一个空数组(甚至通常是预先填充的数组)时,我们希望能够在需要时向其中添加条目。无论我们使用哪种方式创建数组,无论是使用 Array<> 语法还是 [] 类型,我们使用相同的方法将其元素添加进去。我们使用的关键字是 push,它看起来像这样:

emptyGenericStrings.push(30);

如果一次想添加多个元素,可以使用相同的命令来实现:

emptyGenericStrings.push(40,50,60);

无论我们选择一次添加一个条目,还是一次添加多个元素,这些元素都会添加到列表的末尾。这意味着在添加第一个条目后,我们的 list 数组看起来像这样:

The array with a single item added.

添加了第一个条目的数组

现在,如果我们再 push 一个条目到我们的数组中,它会是这样的:

Our array with a second pushed to the end

带有两个条目的数组

删除数组条目

随着时间的推移,项目会变得过时或不必要,因此我们不再需要将它们保留在数组中。如果我们想删除最后一个条目,我们使用 pop 命令。

假设我们从这个数组开始。

Array with four elements

带有 4 个元素的数组

当使用 pop 命令后,我们将只剩下前三个元素,如下所示:

Array with 3 elements left after pop

pop 后剩下 3 个元素的数组

看过一些展示 pop 操作作用的精美图表后,我们实际上将如何使用它?这就像下面的操作一样简单。

const popString = [ 30, 40, 50, 60 ];
popString.pop();

好了,这很简单,但我们如何从列表的其他位置删除单个项目呢?这有点复杂。我们需要使用 indexOf 函数找到要删除记录的索引,然后使用 splice 函数删除该元素。在此示例中,我们正在创建一个 string 数组,然后我们将删除 item2 条目。

const sliceStrings = [ "item1", "item2", "item3", "item4", "item5" ];
const index = sliceStrings.indexOf("item2");
sliceStrings.splice(index, 1);

splice 调用中的第二个参数告诉代码要删除多少个项目。如果我们想删除 item2item3,我们可以使用 splice(index, 2) 来实现。

注意splice 函数会返回你从数组中删除的项目。

假设我们想从数组中删除多个条目。我们该如何做到这一点?有多种方法可以实现。在这些示例中,我们将让事情更有趣一些,并展示数组可以处理比基本类型更多的内容。让我们创建一个吉他类型,我们可以将其添加到数组中。该类型由型号名称和吉他的弦数组成。

interface Guitar {
    model: string,
    strings: number
}
let guitars: Guitar[] = [];

我们将创建一个辅助方法来简化向数组添加条目的过程,然后添加一些条目。

function guitar(model: string, strings: number = 6): Guitar {
    return { model: model, strings: strings};
}
guitars.push(guitar('Fender Stratocaster'));
guitars.push(guitar('Gibson Les Paul Anniversary'));
guitars.push(guitar('Fender Villager', 12));
guitars.push(guitar('Dreadnought 12 String Acoustic', 12));

现在我想做的是删除所有弦数不为六的吉他。我们可以使用的方法之一是过滤数组,使其只包含我们想要的条目。我们必须将过滤后的版本复制回原始数组,以便覆盖它。

guitars = guitars.filter((gtr) => gtr.strings === 6);

现在,虽然我们可以这样做,但我不推荐这种方法。另一种方法是迭代(循环)数组并删除相关条目。要做到这一点,我们必须从最后一个条目开始,然后向后工作到第一个条目,使用 splice 删除我们想删除的条目。如果我们从数组开头开始,我们就有可能错过相邻的条目。

for (let i = guitars.length -1; i >= 0; i--) {
    if (guitars[i].strings !== 6) {
        guitars.splice(i, 1);
    }
}

我们从 length -1 开始可能看起来有点奇怪。我们本能地会认为我们应该从 length 开始,但出于历史原因,数组实际上是从位置 0 开始,而不是从 1 开始。这意味着这里有一个我们必须考虑的偏移量,这就是为什么它是 -1

向数组中插入项

在这篇文章中我想介绍的最后一个常见的数组操作是如何将一个项插入到数组的特定位置,而不是添加到末尾。做到这一点很容易。我们将使用 splice 函数,这次告诉它删除 0 个元素。这个函数非常通用,因为它给我们提供了一个额外的参数来指定我们要添加的元素。如果我想在列表的第二个位置插入另一把吉他,我只需这样做:

guitars.splice(1, 0, guitar('Ibanez Jem 777'));

结论

好了,就是这样。我们已经涵盖了 TypeScript 中数组操作的大部分基础知识。我们知道如何创建空数组和已填充数组,还学习了如何向数组添加和删除项。在下一篇文章中,我们将不再仅仅在控制台中工作,而是开始将 TypeScript 作为 Web 应用程序的伴侣。

一如既往,配套代码可在 Github 上获取。

© . All rights reserved.