sublist
sublist
sublist
sublist
1. 方法介绍
sublist() 是 Dart 中 List 类的一个实例方法,用于从原列表中提取指定范围的元素,返回一个新的列表。
方法签名:
dart
List
2. 参数说明
| 参数 | 类型 | 必需 | 描述 |
|---|---|---|---|
start | int | 是 | 起始索引(包含) |
end | int? | 否 | 结束索引(不包含),默认为列表长度 |
3. 基本用法
3.1 只指定起始位置
1
2
3
List<int> numbers = [1, 2, 3, 4, 5, 6, 7, 8];
List<int> sublist1 = numbers.sublist(2);
print(sublist1); // [3, 4, 5, 6, 7, 8]
3.2 指定起始和结束位置
1
2
3
List<int> numbers = [1, 2, 3, 4, 5, 6, 7, 8];
List<int> sublist2 = numbers.sublist(2, 5);
print(sublist2); // [3, 4, 5]
4. 完整示例代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
void main() {
// 示例列表
List<String> fruits = ['apple', 'banana', 'orange', 'grape', 'mango', 'kiwi'];
print('原始列表: $fruits');
print('列表长度: ${fruits.length}');
print('---');
// 1. 从指定位置到末尾
List<String> fromIndex2 = fruits.sublist(2);
print('从索引2开始: $fromIndex2'); // [orange, grape, mango, kiwi]
// 2. 指定范围
List<String> range2to4 = fruits.sublist(2, 4);
print('索引2到4(不包含4): $range2to4'); // [orange, grape]
// 3. 获取前几个元素
List<String> firstThree = fruits.sublist(0, 3);
print('前三个元素: $firstThree'); // [apple, banana, orange]
// 4. 获取最后几个元素
List<String> lastThree = fruits.sublist(fruits.length - 3);
print('最后三个元素: $lastThree'); // [grape, mango, kiwi]
// 5. 获取中间部分
List<String> middle = fruits.sublist(1, fruits.length - 1);
print('去掉首尾: $middle'); // [banana, orange, grape, mango]
// 6. 复制整个列表
List<String> copy = fruits.sublist(0);
print('完整副本: $copy'); // [apple, banana, orange, grape, mango, kiwi]
// 7. 单个元素
List<String> single = fruits.sublist(3, 4);
print('单个元素: $single'); // [grape]
}
5. 边界情况处理
5.1 处理可能越界的情况
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
void safeSublistExamples() {
List<int> numbers = [1, 2, 3];
// 安全的子列表获取函数
List<T> safeSublist<T>(List<T> list, int start, [int? end]) {
end ??= list.length;
// 确保索引在有效范围内
start = start.clamp(0, list.length);
end = end.clamp(0, list.length);
// 如果起始位置大于等于结束位置,返回空列表
if (start >= end) return [];
return list.sublist(start, end);
}
print('安全获取示例:');
print('正常范围: ${safeSublist(numbers, 1, 3)}'); // [2, 3]
print('起始越界: ${safeSublist(numbers, 5, 10)}'); // []
print('结束越界: ${safeSublist(numbers, 1, 10)}'); // [2, 3]
print('起始>结束: ${safeSublist(numbers, 2, 1)}'); // []
}
5.2 实际应用场景
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
void practicalExamples() {
// 场景1: 分页功能
List<String> allItems = List.generate(100, (index) => 'Item ${index + 1}');
List<String> getPageItems(List<String> items, int page, int pageSize) {
int start = (page - 1) * pageSize;
int end = start + pageSize;
// 防止越界
if (start >= items.length) return [];
if (end > items.length) end = items.length;
return items.sublist(start, end);
}
print('分页示例 - 第2页,每页10条:');
print(getPageItems(allItems, 2, 10));
// 场景2: 时间序列数据截取
List<DateTime> dates = [
DateTime(2024, 1, 1),
DateTime(2024, 1, 2),
DateTime(2024, 1, 3),
DateTime(2024, 1, 4),
DateTime(2024, 1, 5),
];
// 获取最近3天的数据
List<DateTime> recentDates = dates.sublist(dates.length - 3);
print('最近3天: $recentDates');
// 场景3: 数据批处理
List<int> bigData = List.generate(1000, (index) => index);
void processInBatches(List<int> data, int batchSize) {
for (int i = 0; i < data.length; i += batchSize) {
int end = (i + batchSize < data.length) ? i + batchSize : data.length;
List<int> batch = data.sublist(i, end);
print('处理批次 ${i ~/ batchSize + 1}: ${batch.length} 条数据');
// 实际处理逻辑...
}
}
processInBatches(bigData, 100);
}
6. 注意事项
6.1 索引范围验证
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
void indexValidation() {
List<int> numbers = [1, 2, 3, 4, 5];
try {
// 这些会抛出 RangeError
// List<int> error1 = numbers.sublist(-1); // 起始索引为负
// List<int> error2 = numbers.sublist(10); // 起始索引超出范围
// List<int> error3 = numbers.sublist(2, 10); // 结束索引超出范围
// List<int> error4 = numbers.sublist(3, 2); // 起始索引大于结束索引
// 安全的使用方式
int start = 2;
int end = 5;
if (start >= 0 && end <= numbers.length && start <= end) {
List<int> safe = numbers.sublist(start, end);
print('安全获取: $safe');
}
} catch (e) {
print('错误: $e');
}
}
6.2 与其他方法的比较
1
2
3
4
5
6
7
8
9
10
11
12
13
14
void methodComparison() {
List<int> numbers = [1, 2, 3, 4, 5];
// sublist vs getRange
List<int> sublistResult = numbers.sublist(1, 4); // [2, 3, 4]
Iterable<int> rangeResult = numbers.getRange(1, 4); // (2, 3, 4)
List<int> rangeToList = numbers.getRange(1, 4).toList(); // [2, 3, 4]
print('sublist: $sublistResult');
print('getRange: $rangeResult');
print('getRange.toList(): $rangeToList');
// sublist 返回新的 List,getRange 返回 Iterable
}
7. 性能考虑
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
void performanceConsideration() {
// sublist 的时间复杂度是 O(k),其中 k 是子列表的长度
// 对于大型列表,sublist 是高效的
List<int> largeList = List.generate(1000000, (index) => index);
// 高效:只复制需要的部分
Stopwatch stopwatch = Stopwatch()..start();
List<int> sublist = largeList.sublist(500000, 500100);
stopwatch.stop();
print('获取100个元素的子列表耗时: ${stopwatch.elapsedMicroseconds} 微秒');
// 对比:使用 where 过滤(可能更慢)
stopwatch..reset()..start();
List<int> filtered = largeList.where((item) => item >= 500000 && item < 500100).toList();
stopwatch.stop();
print('使用where过滤耗时: ${stopwatch.elapsedMicroseconds} 微秒');
}
总结
sublist() 方法是处理列表切片的最常用和最高效的方式之一。记住:
- 起始索引包含,结束索引不包含
- 始终要处理边界情况,避免
RangeError - 对于大型列表,
sublist比使用where过滤更高效 - 返回的是新列表,对原列表的修改不会影响子列表(除非元素是可变对象)
本文由作者按照 CC BY 4.0 进行授权