1. TakeWhile
TakeWhile 从序列的开始返回元素,直到指定的条件第一次不满足为止
基本用法
var numbers = new[] { 1, 2, 3, 4, 1, 2 };
// 获取小于3的元素,直到遇到第一个不满足条件的元素
var result = numbers.TakeWhile(n => n < 3);
// 结果: [1, 2] // 遇到3时停止
带索引的用法
var words = new[] { "a", "b", "c", "d" };
var result = words.TakeWhile((word, index) =>
word.Length == 1 && index < 2);
// 结果: ["a", "b"]
2. SkipWhile
SkipWhile 跳过序列中的元素,直到条件第一次不满足,然后返回剩余的元素
var numbers = new[] { 1, 2, 3, 4, 1, 2 };
// 跳过小于3的元素,直到遇到第一个不满足条件的元素
var result = numbers.SkipWhile(n => n < 3);
// 结果: [3, 4, 1, 2] // 从3开始取所有元素
带索引的用法
var words = new[] { "a", "b", "c", "d" };
var result = words.SkipWhile((word, index) =>
word.Length == 1 && index < 2);
// 结果: ["c", "d"]
3. 实际应用场景
日志分析
var logEntries = new[] {
"INFO: 系统启动",
"INFO: 加载配置",
"ERROR: 连接失败",
"INFO: 重试连接",
"INFO: 连接成功"
};
// 获取第一个错误之前的所有日志
var beforeError = logEntries.TakeWhile(log => !log.StartsWith("ERROR"));
// 获取第一个错误之后的所有日志
var afterError = logEntries.SkipWhile(log => !log.StartsWith("ERROR"))
.Skip(1); // 跳过错误本身
数据处理
var temperatures = new[] { 20, 21, 23, 25, 19, 18, 22 };
// 获取温度持续上升的部分
var rising = temperatures.TakeWhile((current, index) =>
index == 0 || current > temperatures[index - 1]);
// 跳过温度下降的部分
var afterDrop = temperatures.SkipWhile((current, index) =>
index == 0 || current > temperatures[index - 1]);
4. 注意事项
条件判断
// 条件一旦不满足,后续元素即使满足条件也不会被包含
var numbers = new[] { 1, 2, 5, 3, 1 };
var result = numbers.TakeWhile(n => n < 4);
// 结果: [1, 2] // 5之后的3和1不会被包含
空序列处理
var empty = Enumerable.Empty<int>();
var result = empty.TakeWhile(n => n < 5); // 返回空序列
性能考虑
- 这两个方法都是延迟执行的
- 只在需要时才会计算结果
- 适合处理大数据集
与其他LINQ方法组合
var numbers = Enumerable.Range(1, 100);
var result = numbers
.TakeWhile(n => n <= 50)
.Where(n => n % 2 == 0)
.Select(n => n * n);
这两个方法在处理需要基于条件截取序列的场景时非常有用,尤其是在处理数据流或日志分析等场景中