You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用一步高效LINQ操作筛选对应GPA达标的Grades列表元素?

问题描述

我有两个长度保证一致的double类型列表Grades和GPA,想要创建第三个double类型列表PassingGrades,仅包含Grades中那些索引与GPA中通过测试的元素索引对应的元素。

初始代码如下:

List<double> Grades = new List<double>() { 10, 20, 30, 40, 50, 60, 70, 80, 90, 100 };
List<double> GPA = new List<double>() { 0.4, 0.8, 1.2, 1.6, 2.0, 2.4, 2.8, 3.2, 3.6, 4.0 };
if (Grades.Count != GPA.Count) { return; }
double threshold = 3.0;

我目前的两种实现方式:

  1. 常规for循环写法:
List<double> PassingGrades = new List<double>();
for (int i = 0; i < GPA.Count; i++)
{
    if (GPA[i] >= threshold)
    {
        PassingGrades.Add(Grades[i]);
    }
}
  1. 分两步筛选写法:
var indices = GPA.Select((b, i) => b >= threshold ? i : -1).Where(i => i != -1).ToArray();
List<double> PassingGrades = Grades.Where((g, i) => indices.Contains(i)).ToList();

请问是否存在一种一步实现且效率不低的写法?


解决方案

当然有,你可以使用LINQ的Zip方法实现一步到位的高效筛选。Zip方法会将两个序列中索引对应的元素配对,之后只需筛选出符合GPA阈值条件的配对,再提取对应的Grades元素即可。

这种写法仅需遍历两个序列一次,时间复杂度为O(n),和你写的for循环效率相当,但代码更简洁。

实现代码如下:

List<double> PassingGrades = Grades.Zip(GPA, (grade, gpa) => new { grade, gpa })
                                   .Where(pair => pair.gpa >= threshold)
                                   .Select(pair => pair.grade)
                                   .ToList();

如果不想创建匿名类型,也可以直接在配对逻辑中返回符合条件的grade,写法更紧凑:

List<double> PassingGrades = Grades.Zip(GPA, (grade, gpa) => gpa >= threshold ? grade : (double?)null)
                                   .Where(grade => grade.HasValue)
                                   .Select(grade => grade.Value)
                                   .ToList();

对比你之前的两步写法,那种方式里indices.Contains(i)每次检查都是O(n)操作,整体时间复杂度会变成O(n²),当列表元素较多时效率会明显下降。而Zip的写法既保持了一步实现的简洁性,又保证了和for循环一致的高效性。


内容的提问来源于stack exchange,提问作者Alex

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.17 22:25:25