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

TypeScript 100天 (第7天)

starIconstarIconstarIconstarIconstarIcon

5.00/5 (2投票s)

2023 年 2 月 25 日

CPOL

7分钟阅读

viewsIcon

9910

如何使用数组来管理多个项目

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

什么是数组?

我们可以将数组看作一种方便的方式来创建一组我们可以轻松处理的“事物”。回到我弹奏乐器的例子,我们可以将吉他上的弦看作是“弦”(这里的音乐弦,而不是文本字符串)的集合。在吉他上,每根弦的宽度取决于该弦的音高。现在,如果我们想在代码中引用它们,我们可以选择创建单独的变量,例如 string1string2 等等。这在使用起来会非常麻烦,并且当我们拥有 7 弦、8 弦甚至 12 弦吉他时会限制我们。

使用数组,我们只需要一个数组,然后将各个弦添加到其中即可。

声明数组

我们可以通过多种不同的方式创建数组。如果我们提前知道数组的内容,一种简单的方法是这样创建和填充我们的数组:

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

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

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 函数会返回你从数组中删除的项目。

假设我们想从数组中删除多个条目。我们该如何做?有多种方法可以实现这一点。在这些示例中,我们将稍微调整一下,展示数组不仅能处理基本类型。让我们创建一个 guitar 类型,可以添加到数组中。该类型由型号名称和 guitarstrings 数量组成。

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

现在我想做的是删除任何 guitar,其 strings 的数量不是六个。我们可以使用的第一种方法是过滤数组,使其只返回我们想要的条目。我们必须将过滤后的版本复制回原始数组,以便覆盖它。

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.