在 Rust 中,Range 表示一个区间,通常用于迭代和切片操作。Rust 提供了多种范围类型,各有不同的特性。
1. 基本范围类型
a) 左闭右开范围 start..end
rust
// 包含 start,不包含 end
for i in 0..5 {
println!("{}", i); // 输出 0, 1, 2, 3, 4
}
b) 全闭范围 start..=end
rust
// 包含 start 和 end
for i in 0..=5 {
println!("{}", i); // 输出 0, 1, 2, 3, 4, 5
}
2. 范围创建语法
rust
let range1 = 0..10; // Range
let range2 = 0..=10; // RangeInclusive
let range3 = ..10; // RangeTo
let range4 = ..=10; // RangeToInclusive
let range5 = 5..; // RangeFrom
let range6 = ..; // RangeFull
3. 范围的使用场景
a) 循环迭代
rust
for i in 1..=10 {
println!("Iteration {}", i);
}
for _ in 0..5 {
println!("重复5次");
}
b) 数组/切片切片
rust
let arr = [0, 1, 2, 3, 4, 5];
let slice1 = &arr[1..4]; // [1, 2, 3]
let slice2 = &arr[..3]; // [0, 1, 2]
let slice3 = &arr[2..]; // [2, 3, 4, 5]
let slice4 = &arr[..]; // 整个数组
c) 模式匹配
rust
let x = 5;
match x {
0..=5 => println!("0到5之间"),
6..=10 => println!("6到10之间"),
_ => println!("其他"),
}
4. 范围的方法和特性
包含性检查
rust
let range = 1..10;
assert!(range.contains(&5));
assert!(!range.contains(&10));
let inclusive_range = 1..=10;
assert!(inclusive_range.contains(&10));
范围运算
rust
let r = 0..10;
println!("Start: {:?}", r.start); // 0
println!("End: {:?}", r.end); // 10
// 范围可以迭代
for i in (0..10).step_by(2) {
println!("{}", i); // 0, 2, 4, 6, 8
}
5. 自定义类型支持范围
rust
use std::ops::Range;
// 为自定义类型实现 Index<Range<usize>>
struct MyVec(Vec<i32>);
impl std::ops::Index<Range<usize>> for MyVec {
type Output = [i32];
fn index(&self, index: Range<usize>) -> &Self::Output {
&self.0[index]
}
}
6. 范围和迭代器
范围实现了 Iterator trait:
rust
let sum: i32 = (1..=100).sum();
println!("1到100的和: {}", sum);
let evens: Vec<_> = (0..20).filter(|x| x % 2 == 0).collect();
7. 范围边界类型
范围不仅限于整数:
rust
let char_range = 'a'..='z';
for c in char_range {
print!("{} ", c);
}
// 浮点数不支持 Range(不能迭代),但可以用于比较
let x = 3.14;
if (0.0..1.0).contains(&x) {
println!("在0到1之间");
}
8. 实用技巧
反向范围
rust
for i in (0..5).rev() {
println!("{}", i); // 4, 3, 2, 1, 0
}
范围组合
rust
let r1 = 0..10;
let r2 = 5..15;
// 范围可以比较
assert!(r1.start < r2.start);
范围模式匹配
rust
fn check_range(n: i32) -> &'static str {
match n {
i32::MIN..=-1 => "负数",
0 => "零",
1..=i32::MAX => "正数",
}
}
9. 范围类型总结表
| 语法 | 类型 | 包含 start | 包含 end | 示例 |
|---|---|---|---|---|
a..b |
Range |
✅ | ❌ | 0..5 |
a..=b |
RangeInclusive |
✅ | ✅ | 0..=5 |
..b |
RangeTo |
❌ | ❌ | ..5 |
..=b |
RangeToInclusive |
❌ | ✅ | ..=5 |
a.. |
RangeFrom |
✅ | ❌ | 5.. |
.. |
RangeFull |
❌ | ❌ | .. |
10. 常见陷阱
rust
// 注意:范围是左闭右开的
for i in 0..0 {
// 这里不会执行!
}
// 反向范围需要明确的起点和终点
for i in (5..=1).rev() { // 错误:5..=1 是空范围
// 正确的做法:
// for i in (1..=5).rev()
}
总结
Rust 的范围系统提供了:
- 类型安全:编译时检查范围有效性
- 灵活性:多种范围类型满足不同需求
- 高性能:零成本抽象
- 可组合性:可与迭代器等方法链式调用
范围是 Rust 中非常实用的特性,特别适合处理序列、循环和切片操作。