查找列表中最大的 TestId

发布于 2025-01-19 17:25:33 字数 2615 浏览 1 评论 0原文

我想为每个学生找到最大的 TestId。我正在使用以下代码,希望没有错误。请注意,列表大小可以是任意数字,但每个学生的每个 TestId 都是唯一的数字(学生不能有两个相同的 TestId,意味着每个学生每次测试只能贡献一次)。

在下面的代码中,实际上我首先按 StudentId 对列表进行排序,然后按 TestId 对列表进行排序,然后将每个 StudentId 与下一个进行比较。如果当前和下一个studentId 不相同,则当前Student TestId 取最大的。在这种比较中,第一个和最后一个应该以另一种方式选择。所以我使用了 if 语句来做到这一点(希望是正确的)。

它有效,但我认为还有另一个干净的解决方案可以做到这一点。如果有人知道请帮忙。

static void Main()
    {
        IList<Info> InfoList = new List<Info>{
                    new Info{ StudentId = 1 , TestId = 1 , Point = 10 },
                    new Info{ StudentId = 1 , TestId = 2 , Point = 5 },
                    new Info{ StudentId = 1 , TestId = 3 , Point = 5 },
                    new Info{ StudentId = 2 , TestId = 1 , Point = 6 },
                    new Info{ StudentId = 1 , TestId = 3 , Point = 4 },
                    new Info{ StudentId = 3 , TestId = 1 , Point = 6 },
                    new Info{ StudentId = 4 , TestId = 1 , Point = 9 },
                    new Info{ StudentId = 1 , TestId = 4 , Point = 5 },
                    new Info{ StudentId = 5 , TestId = 2 , Point = 10 },
                    new Info{ StudentId = 2 , TestId = 2 , Point = 8 },
                    new Info{ StudentId = 6 , TestId = 1 , Point = 5 },
                    new Info{ StudentId = 8 , TestId = 1 , Point = 7 }
        }.OrderBy(i => i.StudentId).ThenBy(i => i.TestId).ToList();


        int infoNumber = InfoList.Count;

        IList<Info> InfoList2 = new List<Info>();

        //I am using the followig for loop to find the Biggest TestId for each student.
        for (int i = 0; i < infoNumber; i++)
        {
            if (i + 1 == infoNumber)
            {
                if (InfoList[0].StudentId == InfoList[infoNumber-1].StudentId )
                {
                    InfoList2.Add(InfoList[i]);
                }
                else
                {
                    if ((InfoList[i].StudentId != InfoList[i - 1].StudentId))
                    {
                        InfoList2.Add(InfoList[i]);
                    }
                }
                break;
            }
            if ((InfoList[i].StudentId != InfoList[i + 1].StudentId))
            {
                InfoList2.Add(InfoList[i]);
            }
        }
        //Result
        foreach (var item in InfoList2)
        {
            Console.WriteLine($"StudentId: {item.StudentId}, TestId: {item.TestId}, Point: {item.Point}");
        }
    }
}

public class Info
{
    public int StudentId { get; set; }
    public int TestId { get; set; }
    public double Point { get; set; }
}

I want to find the biggest TestId for each Student. I am using the following code which I hope has no bug. Notice that the list size may be any number but each TestId for each Student is a unique number (A student can not have two the same TestId means each student can just contribute one time i each test).

In the following code, actually I first ordered the list by the studentId then by the TestId, then I compare each StudentId with the next one. If the the current and the next studentId are not the same, the current Studet TestId will have the biggest one. In this kind of comparing the first and the last should be chosen in another way. So I used an if statement to do it (hope is correct).

It works but I think there is another clean solution to do it. If someone knows please help.

static void Main()
    {
        IList<Info> InfoList = new List<Info>{
                    new Info{ StudentId = 1 , TestId = 1 , Point = 10 },
                    new Info{ StudentId = 1 , TestId = 2 , Point = 5 },
                    new Info{ StudentId = 1 , TestId = 3 , Point = 5 },
                    new Info{ StudentId = 2 , TestId = 1 , Point = 6 },
                    new Info{ StudentId = 1 , TestId = 3 , Point = 4 },
                    new Info{ StudentId = 3 , TestId = 1 , Point = 6 },
                    new Info{ StudentId = 4 , TestId = 1 , Point = 9 },
                    new Info{ StudentId = 1 , TestId = 4 , Point = 5 },
                    new Info{ StudentId = 5 , TestId = 2 , Point = 10 },
                    new Info{ StudentId = 2 , TestId = 2 , Point = 8 },
                    new Info{ StudentId = 6 , TestId = 1 , Point = 5 },
                    new Info{ StudentId = 8 , TestId = 1 , Point = 7 }
        }.OrderBy(i => i.StudentId).ThenBy(i => i.TestId).ToList();


        int infoNumber = InfoList.Count;

        IList<Info> InfoList2 = new List<Info>();

        //I am using the followig for loop to find the Biggest TestId for each student.
        for (int i = 0; i < infoNumber; i++)
        {
            if (i + 1 == infoNumber)
            {
                if (InfoList[0].StudentId == InfoList[infoNumber-1].StudentId )
                {
                    InfoList2.Add(InfoList[i]);
                }
                else
                {
                    if ((InfoList[i].StudentId != InfoList[i - 1].StudentId))
                    {
                        InfoList2.Add(InfoList[i]);
                    }
                }
                break;
            }
            if ((InfoList[i].StudentId != InfoList[i + 1].StudentId))
            {
                InfoList2.Add(InfoList[i]);
            }
        }
        //Result
        foreach (var item in InfoList2)
        {
            Console.WriteLine(
quot;StudentId: {item.StudentId}, TestId: {item.TestId}, Point: {item.Point}");
        }
    }
}

public class Info
{
    public int StudentId { get; set; }
    public int TestId { get; set; }
    public double Point { get; set; }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

若无相欠,怎会相见 2025-01-26 17:25:33

使用.NET 6.0 enumoser.maxby,您可以删除orderby,然后做:

var InfoList2 = InfoList.GroupBy(st => st.StudentId)
                        .Select(stg => stg.MaxBy(st => st.TestId));

如果您在较早的.NET上,则可以自己定义它:

public static EnumerableExt {
    public static T MaxBy<T, TKey>(this IEnumerable<T> items, Func<T, TKey> keyFn, Comparer<TKey> keyComparer) => items.Aggregate((a, b) => keyComparer.Compare(keyFn(a), keyFn(b)) >= 0 ? a : b);
    public static T MaxBy<T, TKey>(this IEnumerable<T> items, Func<T, TKey> keyFn) => items.Aggregate((a, b) => Comparer<TKey>.Default.Compare(keyFn(a), keyFn(b)) >= 0 ? a : b);
    public static T MinBy<T, TKey>(this IEnumerable<T> items, Func<T, TKey> keyFn, Comparer<TKey> keyComparer) => items.Aggregate((a, b) => keyComparer.Compare(keyFn(a), keyFn(b)) <= 0 ? a : b);
    public static T MinBy<T, TKey>(this IEnumerable<T> items, Func<T, TKey> keyFn) => items.Aggregate((a, b) => Comparer<TKey>.Default.Compare(keyFn(a), keyFn(b)) <= 0 ? a : b);
}

Using .Net 6.0 Enumerable.MaxBy, you can remove the OrderBy and just do:

var InfoList2 = InfoList.GroupBy(st => st.StudentId)
                        .Select(stg => stg.MaxBy(st => st.TestId));

If you are on earlier .Net, you can define it yourself with:

public static EnumerableExt {
    public static T MaxBy<T, TKey>(this IEnumerable<T> items, Func<T, TKey> keyFn, Comparer<TKey> keyComparer) => items.Aggregate((a, b) => keyComparer.Compare(keyFn(a), keyFn(b)) >= 0 ? a : b);
    public static T MaxBy<T, TKey>(this IEnumerable<T> items, Func<T, TKey> keyFn) => items.Aggregate((a, b) => Comparer<TKey>.Default.Compare(keyFn(a), keyFn(b)) >= 0 ? a : b);
    public static T MinBy<T, TKey>(this IEnumerable<T> items, Func<T, TKey> keyFn, Comparer<TKey> keyComparer) => items.Aggregate((a, b) => keyComparer.Compare(keyFn(a), keyFn(b)) <= 0 ? a : b);
    public static T MinBy<T, TKey>(this IEnumerable<T> items, Func<T, TKey> keyFn) => items.Aggregate((a, b) => Comparer<TKey>.Default.Compare(keyFn(a), keyFn(b)) <= 0 ? a : b);
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文