OrderBy() 列表<> 属性
OrderBy() a List<> property
我在满足特定条件后无法订购列表。情况是我构建了一个用于射程射击的竞赛应用程序,当我要订购结果列表时,我不知道如何使用 OrderBy() 进行处理。
这是我使用的 classes,简化为仅包含对这个问题很重要的属性,镜头 class 没有必要在这里显示。我有一份 ShooterSignup
列表,我正在使用并尝试订购:
ShooterSignup
public class ShooterSignup
{
public List<Serie> Series { get; set;}
}
意甲
public class Serie
{
public List<Shot> Shots { get; set;}
}
我必须按以下条件对结果进行排序:
- 所有系列的总分
- 中心命中数
这两个OrderBy很直接,没问题。但是下一个 OrderBy 步骤是我无法让它工作的地方。下一步的订购方式是:
- 上届意甲联赛的最高分
- 仅次于上一场意甲的最高分
- 前一项得分最高
- ......
以此类推本次比赛拍摄的连续剧数量。我怎样才能达到这个顺序?有可能吗?
编辑:
这是在对 entity framework 的查询中完成的,所以我不能使用在 classes 上创建的任何方法,因为 entity framework 不知道如何将其转换为存储过程
让类定义如下:
public class ShooterSignup
{
public List<Serie> Series { get; set; }
public int GetTotalScore()
{
return Series.Sum(serie => serie.GetScore());
}
public int GetCenterHits()
{
return Series.Sum(serie => serie.GetCenterHits());
}
}
public class Serie
{
public List<Shot> Shots { get; set; }
public int GetScore()
{
return Shots.Sum(shot => shot.Score);
}
public int GetCenterHits()
{
// assume that center hit is a hit with score = 10
return Shots.Count(shot => shot.Score == 10);
}
}
public class Shot
{
public Shot(int score)
{
Score = score;
}
public int Score { get; set; }
}
您可以这样定义 series-wise 比较器:
Comparer<ShooterSignup> seriesComparer = Comparer<ShooterSignup>.Create((a, b) =>
{
using (var enumeratorA = Enumerable.Reverse(a.Series).GetEnumerator())
using (var enumeratorB = Enumerable.Reverse(b.Series).GetEnumerator())
{
bool moveNextA = enumeratorA.MoveNext();
bool moveNextB = enumeratorB.MoveNext();
while (moveNextA && moveNextB)
{
int scoreA = enumeratorA.Current.GetScore();
int scoreB = enumeratorB.Current.GetScore();
if (scoreA != scoreB)
{
return scoreB - scoreA;
}
moveNextA = enumeratorA.MoveNext();
moveNextB = enumeratorB.MoveNext();
}
if (!moveNextA && !moveNextB)
{
return 0;
}
return moveNextA ? 1 : -1;
}
});
现在您可以对 ShooterSignup
的列表进行排序:
var orderedSignups = signups
.OrderBy(s => s.GetTotalScore())
.ThenBy(s => s.GetCenterHits())
.ThenBy(s => s, seriesComparer)
.ToList();
更新。我不确定是否可以形成 LINQ to SQL query that returns ShooterSignup
list in such an order。更简单的方法是从数据库中获取每个 Serie
的累计总数,然后在客户端进行排序。
您可以server-side这样查询:
var seriesTotals = context.Shots
.GroupBy(shot => shot.SerieId)
.Join(context.Series,
g => g.Key,
serie => serie.Id, (grp, serie) => new { grp, serie })
.Join(context.ShooterSignup,
t => t.serie.SignupId, signup => signup.Id,
(t, signup) => new { t, signup })
.OrderByDescending(t => t.t.serie.Id)
.Select(total => new
{
SerieId = total.t.grp.Key,
SignupId = total.signup.Id,
SignupName = total.signup.Name,
SerieScore = total.t.grp.Sum(s => s.Score),
CenterHits = total.t.grp.Count(s => s.Score == 10)
});
结果例如如下:
SerieId
SignupId
SignupName
SerieScore
CenterHits
1
1
A
99
8
2
2
B
95
6
3
1
A
90
3
4
2
B
94
5
现在您可以在客户端按射手分组和订购系列:
var series = seriesTotals.AsEnumerable()
.GroupBy(s => s.SignupId)
.Select(gr => new
{
gr.FirstOrDefault().SignupName,
TotalScore = gr.Sum(s => s.SerieScore),
CenterHits = gr.Sum(s => s.CenterHits),
Scores = string.Join(",", gr.Select(s => s.SerieScore.ToString().PadLeft(3, '0'))) // aggregate all scores in a single string for each ShooterSignup
})
.OrderByDescending(g => g.TotalScore)
.ThenByDescending(g => g.CenterHits)
.ThenByDescending(g => g.Scores)
.ToList();
此查询将生成如下内容:
SignupName
TotalScore
CenterHits
Scores
B
189
11
094,095
A
189
11
090,099
我在满足特定条件后无法订购列表。情况是我构建了一个用于射程射击的竞赛应用程序,当我要订购结果列表时,我不知道如何使用 OrderBy() 进行处理。
这是我使用的 classes,简化为仅包含对这个问题很重要的属性,镜头 class 没有必要在这里显示。我有一份 ShooterSignup
列表,我正在使用并尝试订购:
ShooterSignup
public class ShooterSignup
{
public List<Serie> Series { get; set;}
}
意甲
public class Serie
{
public List<Shot> Shots { get; set;}
}
我必须按以下条件对结果进行排序:
- 所有系列的总分
- 中心命中数
这两个OrderBy很直接,没问题。但是下一个 OrderBy 步骤是我无法让它工作的地方。下一步的订购方式是:
- 上届意甲联赛的最高分
- 仅次于上一场意甲的最高分
- 前一项得分最高
- ......
以此类推本次比赛拍摄的连续剧数量。我怎样才能达到这个顺序?有可能吗?
编辑: 这是在对 entity framework 的查询中完成的,所以我不能使用在 classes 上创建的任何方法,因为 entity framework 不知道如何将其转换为存储过程
让类定义如下:
public class ShooterSignup
{
public List<Serie> Series { get; set; }
public int GetTotalScore()
{
return Series.Sum(serie => serie.GetScore());
}
public int GetCenterHits()
{
return Series.Sum(serie => serie.GetCenterHits());
}
}
public class Serie
{
public List<Shot> Shots { get; set; }
public int GetScore()
{
return Shots.Sum(shot => shot.Score);
}
public int GetCenterHits()
{
// assume that center hit is a hit with score = 10
return Shots.Count(shot => shot.Score == 10);
}
}
public class Shot
{
public Shot(int score)
{
Score = score;
}
public int Score { get; set; }
}
您可以这样定义 series-wise 比较器:
Comparer<ShooterSignup> seriesComparer = Comparer<ShooterSignup>.Create((a, b) =>
{
using (var enumeratorA = Enumerable.Reverse(a.Series).GetEnumerator())
using (var enumeratorB = Enumerable.Reverse(b.Series).GetEnumerator())
{
bool moveNextA = enumeratorA.MoveNext();
bool moveNextB = enumeratorB.MoveNext();
while (moveNextA && moveNextB)
{
int scoreA = enumeratorA.Current.GetScore();
int scoreB = enumeratorB.Current.GetScore();
if (scoreA != scoreB)
{
return scoreB - scoreA;
}
moveNextA = enumeratorA.MoveNext();
moveNextB = enumeratorB.MoveNext();
}
if (!moveNextA && !moveNextB)
{
return 0;
}
return moveNextA ? 1 : -1;
}
});
现在您可以对 ShooterSignup
的列表进行排序:
var orderedSignups = signups
.OrderBy(s => s.GetTotalScore())
.ThenBy(s => s.GetCenterHits())
.ThenBy(s => s, seriesComparer)
.ToList();
更新。我不确定是否可以形成 LINQ to SQL query that returns ShooterSignup
list in such an order。更简单的方法是从数据库中获取每个 Serie
的累计总数,然后在客户端进行排序。
您可以server-side这样查询:
var seriesTotals = context.Shots
.GroupBy(shot => shot.SerieId)
.Join(context.Series,
g => g.Key,
serie => serie.Id, (grp, serie) => new { grp, serie })
.Join(context.ShooterSignup,
t => t.serie.SignupId, signup => signup.Id,
(t, signup) => new { t, signup })
.OrderByDescending(t => t.t.serie.Id)
.Select(total => new
{
SerieId = total.t.grp.Key,
SignupId = total.signup.Id,
SignupName = total.signup.Name,
SerieScore = total.t.grp.Sum(s => s.Score),
CenterHits = total.t.grp.Count(s => s.Score == 10)
});
结果例如如下:
SerieId | SignupId | SignupName | SerieScore | CenterHits |
---|---|---|---|---|
1 | 1 | A | 99 | 8 |
2 | 2 | B | 95 | 6 |
3 | 1 | A | 90 | 3 |
4 | 2 | B | 94 | 5 |
现在您可以在客户端按射手分组和订购系列:
var series = seriesTotals.AsEnumerable()
.GroupBy(s => s.SignupId)
.Select(gr => new
{
gr.FirstOrDefault().SignupName,
TotalScore = gr.Sum(s => s.SerieScore),
CenterHits = gr.Sum(s => s.CenterHits),
Scores = string.Join(",", gr.Select(s => s.SerieScore.ToString().PadLeft(3, '0'))) // aggregate all scores in a single string for each ShooterSignup
})
.OrderByDescending(g => g.TotalScore)
.ThenByDescending(g => g.CenterHits)
.ThenByDescending(g => g.Scores)
.ToList();
此查询将生成如下内容:
SignupName | TotalScore | CenterHits | Scores |
---|---|---|---|
B | 189 | 11 | 094,095 |
A | 189 | 11 | 090,099 |