You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
abp/docs/zh-Hans/UI/Common/Utils/Linked-List.md

1457 lines
22 KiB

# 链表 (双向))
Core模块提供了称为[双链表](https://en.wikipedia.org/wiki/Doubly_linked_list)的实用数据结构. 简而言之双向链表是一系列记录(又称节点),这些记录具有上一个节点,下一个节点及其自身值(或数据)的信息.
## 入门
要创建一个双向链表,你需要做的就是导入和创建它的一个新的实例:
```js
import { LinkedList } from '@abp/ng.core';
const list = new LinkedList();
```
构造函数没有任何参数.
## 用法
### 如何添加新节点
有几种方法可以在链表中创建新节点,这些方法都可以单独使用,也可以通过 `add``addMany` 方法.
#### addHead(value)
```js
addHead(value: T): ListNode\<T\>
```
将给定值添加到链表的第一个节点:
```js
list.addHead('a');
// "a"
list.addHead('b');
// "b" <-> "a"
list.addHead('c');
// "c" <-> "b" <-> "a"
```
#### addManyHead(values)
```js
addManyHead(values: T\[\]): ListNode\<T\>\[\]
```
将给定的多个值添加到链表的第一个节点:
```js
list.addManyHead(['a', 'b', 'c']);
// "a" <-> "b" <-> "c"
list.addManyHead(['x', 'y', 'z']);
// "x" <-> "y" <-> "z" <-> "a" <-> "b" <-> "c"
```
#### addTail(value)
```js
addTail(value: T): ListNode\<T\>
```
将给定值添加到链表的最后一个节点:
```js
list.addTail('a');
// "a"
list.addTail('b');
// "a" <-> "b"
list.addTail('c');
// "a" <-> "b" <-> "c"
```
#### addManyTail(values)
```js
addManyTail(values: T\[\]): ListNode\<T\>\[\]
```
将给定多个值添加到链表的最后一个节点:
```js
list.addManyTail(['a', 'b', 'c']);
// "a" <-> "b" <-> "c"
list.addManyTail(['x', 'y', 'z']);
// "a" <-> "b" <-> "c" <-> "x" <-> "y" <-> "z"
```
#### addAfter(value, previousValue, compareFn)
```js
addAfter(value: T, previousValue: T, compareFn = compare): ListNode\<T\>
```
添加给定值到previousValue节点后:
```js
list.addTail('a');
list.addTail('b');
list.addTail('b');
list.addTail('c');
// "a" <-> "b" <-> "b" <-> "c"
list.addAfter('x', 'b');
// "a" <-> "b" <-> "x" <-> "b" <-> "c"
```
你可以自定义比较器:
```js
list.addTail({ x: 1 });
list.addTail({ x: 2 });
list.addTail({ x: 3 });
// {"x":1} <-> {"x":2} <-> {"x":3}
list.addAfter(
{ x: 0 },
2,
(value, searchedValue) => value.x === searchedValue
);
// {"x":1} <-> {"x":2} <-> {"x":0} <-> {"x":3}
```
> 默认的比较函数检查深度相等性,因此你几乎不需要传递该参数.
#### addManyAfter(values, previousValue, compareFn)
```js
addManyAfter(values: T\[\], previousValue: T, compareFn = compare): ListNode\<T\>\[\]
```
添加给定的多个值到previousValue节点后:
```js
list.addManyTail(['a', 'b', 'b', 'c']);
// "a" <-> "b" <-> "b" <-> "c"
list.addManyAfter(['x', 'y'], 'b');
// "a" <-> "b" <-> "x" <-> "y" <-> "b" <-> "c"
```
你可以自定义比较器:
```js
list.addManyTail([{ x: 1 },{ x: 2 },{ x: 3 }]);
// {"x":1} <-> {"x":2} <-> {"x":3}
list.addManyAfter(
[{ x: 4 }, { x: 5 }],
2,
(value, searchedValue) => value.x === searchedValue
);
// {"x":1} <-> {"x":2} <-> {"x":4} <-> {"x":5} <-> {"x":3}
```
> 默认的比较函数检查深度相等性,因此你几乎不需要传递该参数.
#### addBefore(value, nextValue, compareFn)
```js
addBefore(value: T, nextValue: T, compareFn = compare): ListNode\<T\>
```
添加给值到previousValue节点前:
```js
list.addTail('a');
list.addTail('b');
list.addTail('b');
list.addTail('c');
// "a" <-> "b" <-> "b" <-> "c"
list.addBefore('x', 'b');
// "a" <-> "x" <-> "b" <-> "b" <-> "c"
```
你可以自定义比较器:
```js
list.addTail({ x: 1 });
list.addTail({ x: 2 });
list.addTail({ x: 3 });
// {"x":1} <-> {"x":2} <-> {"x":3}
list.addBefore(
{ x: 0 },
2,
(value, searchedValue) => value.x === searchedValue
);
// {"x":1} <-> {"x":0} <-> {"x":2} <-> {"x":3}
```
> 默认的比较函数检查深度相等性,因此你几乎不需要传递该参数.
#### addManyBefore(values, nextValue, compareFn)
```js
addManyBefore(values: T\[\], nextValue: T, compareFn = compare): ListNode\<T\>\[\]
```
添加给定的多个值到previousValue节点前:
```js
list.addManyTail(['a', 'b', 'b', 'c']);
// "a" <-> "b" <-> "b" <-> "c"
list.addManyBefore(['x', 'y'], 'b');
// "a" <-> "x" <-> "y" <-> "b" <-> "b" <-> "c"
```
你可以自定义比较器
```js
list.addManyTail([{ x: 1 },{ x: 2 },{ x: 3 }]);
// {"x":1} <-> {"x":2} <-> {"x":3}
list.addManyBefore(
[{ x: 4 }, { x: 5 }],
2,
(value, searchedValue) => value.x === searchedValue
);
// {"x":1} <-> {"x":4} <-> {"x":5} <-> {"x":2} <-> {"x":3}
```
> 默认的比较函数检查深度相等性,因此你几乎不需要传递该参数.
#### addByIndex(value, position)
```js
addByIndex(value: T, position: number): ListNode\<T\>
```
在链表的指定位置添加节点:
```js
list.addTail('a');
list.addTail('b');
list.addTail('c');
// "a" <-> "b" <-> "c"
list.addByIndex('x', 2);
// "a" <-> "b" <-> "x" <-> "c"
```
它也适用于负索引:
```js
list.addTail('a');
list.addTail('b');
list.addTail('c');
// "a" <-> "b" <-> "c"
list.addByIndex('x', -1);
// "a" <-> "b" <-> "x" <-> "c"
```
#### addManyByIndex(values, position)
```js
addManyByIndex(values: T\[\], position: number): ListNode\<T\>\[\]
```
添加多个节点到链表的指定位置:
```js
list.addManyTail(['a', 'b', 'c']);
// "a" <-> "b" <-> "c"
list.addManyByIndex(['x', 'y'], 2);
// "a" <-> "b" <-> "x" <-> "y" <-> "c"
```
它也适用于负索引:
```js
list.addManyTail(['a', 'b', 'c']);
// "a" <-> "b" <-> "c"
list.addManyByIndex(['x', 'y'], -1);
// "a" <-> "b" <-> "x" <-> "y" <-> "c"
```
#### add(value).head()
```js
add(value: T).head(): ListNode\<T\>
```
将添加的节点移动到链表头:
```js
list.add('a').head();
// "a"
list.add('b').head();
// "b" <-> "a"
list.add('c').head();
// "c" <-> "b" <-> "a"
```
> 它是 `addHead` 的替代API.
#### add(value).tail()
```js
add(value: T).tail(): ListNode\<T\>
```
将添加的节点移动到链表尾:
```js
list.add('a').tail();
// "a"
list.add('b').tail();
// "a" <-> "b"
list.add('c').tail();
// "a" <-> "b" <-> "c"
```
> 它是 `addTail` 的替代API.
#### add(value).after(previousValue, compareFn)
```js
add(value: T).after(previousValue: T, compareFn = compare): ListNode\<T\>
```
将添加的节点移动到指定节点后:
```js
list.add('a').tail();
list.add('b').tail();
list.add('b').tail();
list.add('c').tail();
// "a" <-> "b" <-> "b" <-> "c"
list.add('x').after('b');
// "a" <-> "b" <-> "x" <-> "b" <-> "c"
```
你可以自定义比较器
```js
list.add({ x: 1 }).tail();
list.add({ x: 2 }).tail();
list.add({ x: 3 }).tail();
// {"x":1} <-> {"x":2} <-> {"x":3}
list
.add({ x: 0 })
.after(2, (value, searchedValue) => value.x === searchedValue);
// {"x":1} <-> {"x":2} <-> {"x":0} <-> {"x":3}
```
> 它是 `addAfter` 的替代API.
>
> 默认的比较函数检查深度相等性,因此你几乎不需要传递该参数.
#### add(value).before(nextValue, compareFn)
```js
add(value: T).before(nextValue: T, compareFn = compare): ListNode\<T\>
```
将添加的节点移动到指定节点前:
```js
list.add('a').tail();
list.add('b').tail();
list.add('b').tail();
list.add('c').tail();
// "a" <-> "b" <-> "b" <-> "c"
list.add('x').before('b');
// "a" <-> "x" <-> "b" <-> "b" <-> "c"
```
你可以自定义比较器
```js
list.add({ x: 1 }).tail();
list.add({ x: 2 }).tail();
list.add({ x: 3 }).tail();
// {"x":1} <-> {"x":2} <-> {"x":3}
list
.add({ x: 0 })
.before(2, (value, searchedValue) => value.x === searchedValue);
// {"x":1} <-> {"x":0} <-> {"x":2} <-> {"x":3}
```
> 它是 `addBefore` 的替代API.
>
> 默认的比较函数检查深度相等性,因此你几乎不需要传递该参数.
#### add(value).byIndex(position)
```js
add(value: T).byIndex(position: number): ListNode\<T\>
```
将添加的节点移动到链表指定位置:
```js
list.add('a').tail();
list.add('b').tail();
list.add('c').tail();
// "a" <-> "b" <-> "c"
list.add('x').byIndex(2);
// "a" <-> "b" <-> "x" <-> "c"
```
它也适用于负索引:
```js
list.add('a').tail();
list.add('b').tail();
list.add('c').tail();
// "a" <-> "b" <-> "c"
list.add('x').byIndex(-1);
// "a" <-> "b" <-> "x" <-> "c"
```
> 它是 `addByIndex` 的替代API.
#### addMany(values).head()
```js
addMany(values: T\[\]).head(): ListNode\<T\>\[\]
```
将添加的多个节点移动到链表头:
```js
list.addMany(['a', 'b', 'c']).head();
// "a" <-> "b" <-> "c"
list.addMany(['x', 'y', 'z']).head();
// "x" <-> "y" <-> "z" <-> "a" <-> "b" <-> "c"
```
> 它是 `addManyHead` 的替代API.
#### addMany(values).tail()
```js
addMany(values: T\[\]).tail(): ListNode\<T\>\[\]
```
将添加的多个节点移动到链表尾:
```js
list.addMany(['a', 'b', 'c']).tail();
// "a" <-> "b" <-> "c"
list.addMany(['x', 'y', 'z']).tail();
// "a" <-> "b" <-> "c" <-> "x" <-> "y" <-> "z"
```
> 它是 `addManyTail` 的替代API.
#### addMany(values).after(previousValue, compareFn)
```js
addMany(values: T\[\]).after(previousValue: T, compareFn = compare): ListNode\<T\>\[\]
```
将添加的多个节点移动到指定节点后:
```js
list.addMany(['a', 'b', 'b', 'c']).tail();
// "a" <-> "b" <-> "b" <-> "c"
list.addMany(['x', 'y']).after('b');
// "a" <-> "b" <-> "x" <-> "y" <-> "b" <-> "c"
```
你可以自定义比较器
```js
list.addMany([{ x: 1 }, { x: 2 }, { x: 3 }]).tail();
// {"x":1} <-> {"x":2} <-> {"x":3}
list
.addMany([{ x: 4 }, { x: 5 }])
.after(2, (value, searchedValue) => value.x === searchedValue);
// {"x":1} <-> {"x":2} <-> {"x":4} <-> {"x":5} <-> {"x":3}
```
> 它是 `addManyAfter` 的替代API.
>
> 默认的比较函数检查深度相等性,因此你几乎不需要传递该参数.
#### addMany(values).before(nextValue, compareFn)
```js
addMany(values: T\[\]).before(nextValue: T, compareFn = compare): ListNode\<T\>\[\]
```
将添加的多个节点移动到指定节点前:
```js
list.addMany(['a', 'b', 'b', 'c']).tail();
// "a" <-> "b" <-> "b" <-> "c"
list.addMany(['x', 'y']).before('b');
// "a" <-> "x" <-> "y" <-> "b" <-> "b" <-> "c"
```
你可以自定义比较器
```js
list.addMany([{ x: 1 }, { x: 2 }, { x: 3 }]).tail();
// {"x":1} <-> {"x":2} <-> {"x":3}
list
.addMany([{ x: 4 }, { x: 5 }])
.before(2, (value, searchedValue) => value.x === searchedValue);
// {"x":1} <-> {"x":4} <-> {"x":5} <-> {"x":2} <-> {"x":3}
```
> 它是 `addManyBefore` 的替代API.
>
> 默认的比较函数检查深度相等性,因此你几乎不需要传递该参数.
#### addMany(values).byIndex(position)
```js
addMany(values: T\[\]).byIndex(position: number): ListNode\<T\>\[\]
```
将添加的多个节点移动到链表的指定位置:
```js
list.addMany(['a', 'b', 'c']).tail();
// "a" <-> "b" <-> "c"
list.addMany(['x', 'y']).byIndex(2);
// "a" <-> "b" <-> "x" <-> "y" <-> "c"
```
它也适用于负索引:
```js
list.addMany(['a', 'b', 'c']).tail();
// "a" <-> "b" <-> "c"
list.addMany(['x', 'y']).byIndex(-1);
// "a" <-> "b" <-> "x" <-> "y" <-> "c"
```
> 它是 `addManyByIndex` 的替代API.
### 如何删除节点
有几种方法可以在链表中删除节点,这些方法都可以单独使用,也可以通过 `drop` 方法.
#### dropHead()
```js
dropHead(): ListNode\<T\> | undefined
```
删除链表的第一个节点:
```js
list.addMany(['a', 'b', 'c']).tail();
// "a" <-> "b" <-> "c"
list.dropHead();
// "b" <-> "c"
```
#### dropManyHead(count)
```js
dropManyHead(count: number): ListNode\<T\>\[\]
```
删除指定数量的链表的头节点:
```js
list.addMany(['a', 'b', 'c']).tail();
// "a" <-> "b" <-> "c"
list.dropManyHead(2);
// "c"
```
#### dropTail()
```js
dropTail(): ListNode\<T\> | undefined
```
删除链表的最后一个节点:
```js
list.addMany(['a', 'b', 'c']).tail();
// "a" <-> "b" <-> "c"
list.dropTail();
// "a" <-> "b"
```
#### dropManyTail(count)
```js
dropManyTail(count: number): ListNode\<T\>\[\]
```
删除指定数量的链表的尾节点:
```js
list.addMany(['a', 'b', 'c']).tail();
// "a" <-> "b" <-> "c"
list.dropManyTail(2);
// "a"
```
#### dropByIndex(position)
```js
dropByIndex(position: number): ListNode\<T\> | undefined
```
删除链表中给定位置的节点:
```js
list.addMany(['a', 'b', 'c']).tail();
// "a" <-> "b" <-> "c"
list.dropByIndex(1);
// "a" <-> "c"
```
它也适用于负索引:
```js
list.addMany(['a', 'b', 'c']).tail();
// "a" <-> "b" <-> "c"
list.dropByIndex(-2);
// "a" <-> "c"
```
#### dropManyByIndex(count, position)
```js
dropManyByIndex(count: number, position: number): ListNode\<T\>\[\]
```
删除链表中给定位置与数量的多个节点:
```js
list.addMany(['a', 'b', 'c', 'd']).tail();
// "a" <-> "b" <-> "c" <-> "d
list.dropManyByIndex(2, 1);
// "a" <-> "d"
```
它也适用于负索引:
```js
list.addMany(['a', 'b', 'c', 'd']).tail();
// "a" <-> "b" <-> "c" <-> "d
list.dropManyByIndex(2, -2);
// "a" <-> "d"
```
#### dropByValue(value, compareFn)
```js
dropByValue(value: T, compareFn = compare): ListNode\<T\> | undefined
```
删除链表中含有给定值的第一个节点:
```js
list.addMany(['a', 'x', 'b', 'x', 'c']).tail();
// "a" <-> "x" <-> "b" <-> "x" <-> "c"
list.dropByValue('x');
// "a" <-> "b" <-> "x" <-> "c"
```
你可以自定义比较器
```js
list.addMany([{ x: 1 }, { x: 0 }, { x: 2 }, { x: 0 }, { x: 3 }]).tail();
// {"x":1} <-> {"x":0} <-> {"x":2} <-> {"x":0} <-> {"x":3}
list.dropByValue(0, (value, searchedValue) => value.x === searchedValue);
// {"x":1} <-> {"x":2} <-> {"x":0} <-> {"x":3}
```
> 默认的比较函数检查深度相等性,因此你几乎不需要传递该参数.
#### dropByValueAll(value, compareFn)
```js
dropByValueAll(value: T, compareFn = compare): ListNode\<T\>\[\]
```
删除链表中含有给定值的所有节点:
```js
list.addMany(['a', 'x', 'b', 'x', 'c']).tail();
// "a" <-> "x" <-> "b" <-> "x" <-> "c"
list.dropByValueAll('x');
// "a" <-> "b" <-> "c"
```
你可以自定义比较器
```js
list.addMany([{ x: 1 }, { x: 0 }, { x: 2 }, { x: 0 }, { x: 3 }]).tail();
// {"x":1} <-> {"x":0} <-> {"x":2} <-> {"x":0} <-> {"x":3}
list.dropByValue(0, (value, searchedValue) => value.x === searchedValue);
// {"x":1} <-> {"x":2} <-> {"x":3}
```
> 默认的比较函数检查深度相等性,因此你几乎不需要传递该参数.
#### drop().head()
```js
drop().head(): ListNode\<T\> | undefined
```
删除链表的头节点:
```js
list.addMany(['a', 'b', 'c']).tail();
// "a" <-> "b" <-> "c"
list.drop().head();
// "b" <-> "c"
```
> 它是 `dropHead` 的替代API.
#### drop().tail()
```js
drop().tail(): ListNode\<T\> | undefined
```
删除链表的尾节点:
```js
list.addMany(['a', 'b', 'c']).tail();
// "a" <-> "b" <-> "c"
list.drop().tail();
// "a" <-> "b"
```
> 它是 `dropTail` 的替代API.
#### drop().byIndex(position)
```js
drop().byIndex(position: number): ListNode\<T\> | undefined
```
删除链表指定位置的节点:
```js
list.addMany(['a', 'b', 'c']).tail();
// "a" <-> "b" <-> "c"
list.drop().byIndex(1);
// "a" <-> "c"
```
它也适用于负索引:
```js
list.addMany(['a', 'b', 'c']).tail();
// "a" <-> "b" <-> "c"
list.drop().byIndex(-2);
// "a" <-> "c"
```
> 它是 `dropByIndex` 的替代API.
#### drop().byValue(value, compareFn)
```js
drop().byValue(value: T, compareFn = compare): ListNode\<T\> | undefined
```
删除链表中含有给定值的第一个节点:
```js
list.addMany(['a', 'x', 'b', 'x', 'c']).tail();
// "a" <-> "x" <-> "b" <-> "x" <-> "c"
list.drop().byValue('x');
// "a" <-> "b" <-> "x" <-> "c"
```
你可以自定义比较器
```js
list.addMany([{ x: 1 }, { x: 0 }, { x: 2 }, { x: 0 }, { x: 3 }]).tail();
// {"x":1} <-> {"x":0} <-> {"x":2} <-> {"x":0} <-> {"x":3}
list
.drop()
.byValue(0, (value, searchedValue) => value.x === searchedValue);
// {"x":1} <-> {"x":2} <-> {"x":0} <-> {"x":3}
```
> 它是 `dropByValue` 的替代API.
>
> 默认的比较函数检查深度相等性,因此你几乎不需要传递该参数.
#### drop().byValueAll(value, compareFn)
```js
drop().byValueAll(value: T, compareFn = compare): ListNode\<T\>\[\]
```
删除链表中含有给定值的所有节点:
```js
list.addMany(['a', 'x', 'b', 'x', 'c']).tail();
// "a" <-> "x" <-> "b" <-> "x" <-> "c"
list.drop().byValueAll('x');
// "a" <-> "b" <-> "c"
```
你可以自定义比较器
```js
list.addMany([{ x: 1 }, { x: 0 }, { x: 2 }, { x: 0 }, { x: 3 }]).tail();
// {"x":1} <-> {"x":0} <-> {"x":2} <-> {"x":0} <-> {"x":3}
list
.drop()
.byValueAll(0, (value, searchedValue) => value.x === searchedValue);
// {"x":1} <-> {"x":2} <-> {"x":3}
```
> 它是 `dropByValueAll` 的替代API.
>
> 默认的比较函数检查深度相等性,因此你几乎不需要传递该参数.
#### dropMany(count).head()
```js
dropMany(count: number).head(): ListNode\<T\>\[\]
```
删除链表中指定数量的头节点:
```js
list.addMany(['a', 'b', 'c']).tail();
// "a" <-> "b" <-> "c"
list.dropMany(2).head();
// "c"
```
> 它是 `dropManyHead` 的替代API.
#### dropMany(count).tail()
```js
dropMany(count: number).tail(): ListNode\<T\>\[\]
```
删除链表中指定数量的尾节点::
```js
list.addMany(['a', 'b', 'c']).tail();
// "a" <-> "b" <-> "c"
list.dropMany(2).tail();
// "a"
```
> 它是 `dropManyTail` 的替代API.
#### dropMany(count).byIndex(position)
```js
dropMany(count: number).byIndex(position: number): ListNode\<T\>\[\]
```
删除链表中指定位置和数量的节点:
```js
list.addMany(['a', 'b', 'c', 'd']).tail();
// "a" <-> "b" <-> "c" <-> "d
list.dropMany(2).byIndex(1);
// "a" <-> "d"
```
它也适用于负索引:
```js
list.addMany(['a', 'b', 'c', 'd']).tail();
// "a" <-> "b" <-> "c" <-> "d
list.dropMany(2).byIndex(-2);
// "a" <-> "d"
```
> 它是 `dropManyByIndex` 的替代API.
### 如何查找节点
有几个方法找到链表特定节点.
#### find(predicate)
```js
find(predicate: ListIteratorFunction\<T\>): ListNode\<T\> | undefined
```
从链表中找到与给定谓词匹配的第一个节点:
```js
list.addTailMany(['a', 'b', 'b', 'c']);
// "a" <-> "b" <-> "b" <-> "c"
const found = list.find(node => node.value === 'b');
/*
found.value === "b"
found.previous.value === "a"
found.next.value === "b"
*/
```
#### findIndex(predicate)
```js
findIndex(predicate: ListIteratorFunction\<T\>): number
```
从链表中找到与给定谓词匹配的第一个节点的位置:
```js
list.addTailMany(['a', 'b', 'b', 'c']);
// "a" <-> "b" <-> "b" <-> "c"
const i0 = list.findIndex(node => node.next && node.next.value === 'b');
const i1 = list.findIndex(node => node.value === 'b');
const i2 = list.findIndex(node => node.previous && node.previous.value === 'b');
const i3 = list.findIndex(node => node.value === 'x');
/*
i0 === 0
i1 === 1
i2 === 2
i3 === -1
*/
```
#### get(position)
```js
get(position: number): ListNode\<T\> | undefined
```
查找并返回链表中特定位置的节点:
```js
list.addTailMany(['a', 'b', 'c']);
// "a" <-> "b" <-> "c"
const found = list.get(1);
/*
found.value === "b"
found.previous.value === "a"
found.next.value === "c"
*/
```
#### indexOf(value, compareFn)
```js
indexOf(value: T, compareFn = compare): number
```
在链表中找到匹配给定值的第一个节点位置:
```js
list.addTailMany(['a', 'b', 'b', 'c']);
// "a" <-> "b" <-> "b" <-> "c"
const i0 = list.indexOf('a');
const i1 = list.indexOf('b');
const i2 = list.indexOf('c');
const i3 = list.indexOf('x');
/*
i0 === 0
i1 === 1
i2 === 3
i3 === -1
*/
```
你可以自定义比较器
```js
list.addTailMany([{ x: 1 }, { x: 0 }, { x: 2 }, { x: 0 }, { x: 3 }]);
// {"x":1} <-> {"x":0} <-> {"x":2} <-> {"x":0} <-> {"x":3}
const i0 = indexOf(1, (value, searchedValue) => value.x === searchedValue);
const i1 = indexOf(2, (value, searchedValue) => value.x === searchedValue);
const i2 = indexOf(3, (value, searchedValue) => value.x === searchedValue);
const i3 = indexOf(0, (value, searchedValue) => value.x === searchedValue);
const i4 = indexOf(4, (value, searchedValue) => value.x === searchedValue);
/*
i0 === 0
i1 === 2
i2 === 4
i3 === 1
i4 === -1
*/
```
> 默认的比较函数检查深度相等性,因此你几乎不需要传递该参数.
### 如何检查所有节点
有几种方法来遍历或显示一个链表.
#### forEach(callback)
```js
forEach(callback: ListIteratorFunction\<T\>): void
```
从头到尾在链表中的所有节点上运行回调函数:
```js
list.addTailMany(['a', 'b', 'c']);
// "a" <-> "b" <-> "c"
list.forEach((node, index) => console.log(node.value + index));
// 'a0'
// 'b1'
// 'c2'
```
#### \*\[Symbol.iterator\]\(\)
A linked list is iterable. In other words, you may use methods like `for...of` on it.
```js
list.addTailMany(['a', 'b', 'c']);
// "a" <-> "b" <-> "c"
for(const node of list) {
console.log(node.value);
}
// 'a'
// 'b'
// 'c'
```
#### toArray()
```js
toArray(): T\[\]
```
Converts a linked list to an array of values:
```js
list.addTailMany(['a', 'b', 'c']);
// "a" <-> "b" <-> "c"
const arr = list.toArray();
/*
arr === ['a', 'b', 'c']
*/
```
#### toNodeArray()
```js
toNodeArray(): T\[\]
```
Converts a linked list to an array of nodes:
```js
list.addTailMany(['a', 'b', 'c']);
// "a" <-> "b" <-> "c"
const arr = list.toNodeArray();
/*
arr[0].value === 'a'
arr[1].value === 'a'
arr[2].value === 'a'
*/
```
#### toString()
```js
toString(): string
```
Converts a linked list to a string representation of nodes and their relations:
```js
list.addTailMany(['a', 2, 'c', { k: 4, v: 'd' }]);
// "a" <-> 2 <-> "c" <-> {"k":4,"v":"d"}
const str = list.toString();
/*
str === '"a" <-> 2 <-> "c" <-> {"k":4,"v":"d"}'
*/
```
You may pass a custom mapper function to map values before stringifying them:
```js
list.addMany([{ x: 1 }, { x: 2 }, { x: 3 }, { x: 4 }, { x: 5 }]).tail();
// {"x":1} <-> {"x":2} <-> {"x":3} <-> {"x":4} <-> {"x":5}
const str = list.toString(value => value.x);
/*
str === '1 <-> 2 <-> 3 <-> 4 <-> 5'
*/
```