linq操作DataTable计算排名的问题

发布于 2021-11-19 01:39:15 字数 1334 浏览 988 评论 9

我有一个DataTable存储有学生的成绩,我想要对其进行计算排名,想用linq实现,现在使用如下代码,想请教一下各位强人,是否有更简洁快速的方法?

void testLinq()
        {
            DataTable dt = new DataTable();
            dt.Columns.Add("成绩");
            dt.Columns.Add("排名");
            dt.Rows.Add(new object[] { 12, null });
            dt.Rows.Add(new object[] { 120, null });
            dt.Rows.Add(new object[] { 92, null });
            System.Diagnostics.Debug.WriteLine("成绩    排名");
            foreach (DataRow row in dt.Rows)
            {
                float cj = float.Parse(row["成绩"].ToString());

                //Linq操作DataTable:
                int rank = (from dt1 in dt.AsEnumerable()
                            where float.Parse(dt1.Field<string>("成绩")) > cj//条件  
                            select dt1).Count() + 1;
                /*IEnumerable<DataRow> rows = dt.AsEnumerable().Where(t => (float.Parse(t.Field<string>("成绩")) > cj));
                int rank = rows.Count() + 1;*/

                row["排名"] = rank;

                System.Diagnostics.Debug.WriteLine(cj.ToString()+"    "+rank.ToString());
            }
        }
输出:

成绩    排名
12    3
120    1
92    2

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

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

发布评论

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

评论(9

疑心病 2021-11-25 14:02:04

非常感谢。。。

孤檠 2021-11-25 13:59:32

楼上有点偏了。如果愿意牺牲一点空间的话,直接select出来所有成绩排序后转成数组,循环所有datarow赋值成绩在数组里的index就行了。

var lstGrade = dt.AsEnumerable().Select(r => float.Parse(r.Field<string>("成绩"))).OrderByDescending(n => n).ToList();

            foreach (DataRow row in dt.Rows)
            {
                float cj = float.Parse(row["成绩"].ToString());

                int rank = lstGrade.IndexOf(cj) + 1;

                row["排名"] = rank;

                Console.WriteLine(cj.ToString() + "    " + rank.ToString());
            }

平生欢 2021-11-25 13:32:00

详细点?我希望是不修改原DataTable表中各数据的排序,增加排名数据。

情绪失控 2021-11-25 13:06:48

回复
手头没有环境, 最迟下午答复你...

鹤舞 2021-11-25 08:11:51

居然百度不到System.Interactive,还是得谷歌,MoreLinq?

空城仅有旧梦在 2021-11-25 03:21:19

代码中将成绩都当作int处理了,不太合适,成绩可以有小数的如96.5分

绝影如岚 2021-11-24 22:54:59

回复
int那个只是例子罢了你可以自由设置数据类型. 至于Interactive, 使用nuget插件在线搜索"ix", 选择安装Ix-main即可

清晨说ぺ晚安 2021-11-22 21:24:44

非常感谢。

旧伤慢歌 2021-11-22 17:55:45
var dt = new DataTable();
            dt.Columns.Add("成绩");
            dt.Columns.Add("排名");
            dt.Rows.Add(90, -1);
            dt.Rows.Add(120, -1);
            dt.Rows.Add(70, -1);
            dt.Rows.Add(90, -1);
            dt.Rows.Add(120, -1);
            dt.Rows.Add(90, -1);

            Console.WriteLine("成绩t排名");
            var dict =
                dt.Rows.OfType<DataRow>()
                    .Select(r => int.Parse(r["成绩"].ToString()))
                    .OrderByDescending(n => n)
                    .Select((n, i) => new {成绩 = n, 排名 = i + 1})
                    .Distinct(p => p.成绩)
                    .ToDictionary(p => p.成绩.ToString(), p => p.排名.ToString());
            dt.Rows.OfType<DataRow>().ForEach(r => r["排名"] = dict[r["成绩"].ToString()]);
            dt.Rows.OfType<DataRow>().ForEach(r => Console.WriteLine("{0}t{1}", r["成绩"], r["排名"]));

麻烦之处主要在于需要处理成绩相同的排名问题,比如最高分两个100,那么99分的排名是第三之类的。再就是这个DataTable如果是能手工设计的话程序会更容易一些,比如:

var dt = new MyDataSet.成绩排行DataTable();
            dt.Add成绩排行Row(90, -1);
            dt.Add成绩排行Row(120, -1);
            dt.Add成绩排行Row(70, -1);
            dt.Add成绩排行Row(90, -1);
            dt.Add成绩排行Row(120, -1);
            dt.Add成绩排行Row(90, -1);

            Console.WriteLine("成绩t排名");
            var dict =
                dt.Select(r => r.成绩)
                    .OrderByDescending(n => n)
                    .Select((n, i) => new { 成绩 = n, 排名 = i + 1 })
                    .Distinct(p => p.成绩)
                    .ToDictionary(p => p.成绩, p => p.排名);
            dt.ForEach(r => r.排名 = dict[r.成绩]);
            dt.ForEach(r => Console.WriteLine("{0}t{1}", r.成绩, r.排名));

其中Distinct和ForEach来自官方System.Interactive扩展。

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文