将两个列表的内容与linq(C#)进行比较,以查看一个特定值是否在特定范围内
好吧,为了今天的好日子,我已经在我的头上摔碎了 我有两个自定义对象列表,其中一个属性在两个列表中相同。我需要遍历这两个列表,看看属性是否相同 我可以用嵌套for each循环来实现,但如果我能用LINQ实现同样的功能,我会很不情愿(我相信我可以做到)。 我已经尝试了几乎所有的方法,但我就是找不到我想要的解决方案 下面是我用于列表的对象的代码将两个列表的内容与linq(C#)进行比较,以查看一个特定值是否在特定范围内,c#,linq,loops,lambda,foreach,C#,Linq,Loops,Lambda,Foreach,好吧,为了今天的好日子,我已经在我的头上摔碎了 我有两个自定义对象列表,其中一个属性在两个列表中相同。我需要遍历这两个列表,看看属性是否相同 我可以用嵌套for each循环来实现,但如果我能用LINQ实现同样的功能,我会很不情愿(我相信我可以做到)。 我已经尝试了几乎所有的方法,但我就是找不到我想要的解决方案 下面是我用于列表的对象的代码 public class Game { // Fields private short maxPlayers; private Te
public class Game
{
// Fields
private short maxPlayers;
private Team axis;
private Team allies;
// Properties
public string Name { get; set; }
public short MaxPlayers
{
get
{
return maxPlayers;
}
set
{
if (value > 8)
maxPlayers = 8;
else if (value < 2)
maxPlayers = 2;
else
maxPlayers = value;
}
}
public short CurrentPlayers
{
get
{
int players = axis.Players.Count + allies.Players.Count;
return (short)players;
}
}
public bool IsFull
{
get
{
if (CurrentPlayers == MaxPlayers)
return true;
else
return false;
}
}
public Team Axis { get; set; }
public Team Allies { get; set; }
public List<Player> Players
{
// Somehow this does not work either, so I had to stick with one single team in the for-each loops. Ideas to fix?
get
{
if (allies.Players.Count == 0)
return axis.Players.Concat(allies.Players).ToList();
else
return allies.Players.Concat(axis.Players).ToList();
}
}
//Constructor
public Game()
{
axis = new Team();
allies = new Team();
}
}
public class Team
{
public List<Player> Players { get; set; }
public EFaction Faction { get; set; }
public enum EFaction
{
Allies,
Axis,
Random
}
public Team()
{
Players = new List<Player>();
Faction = EFaction.Random;
}
}
public class Player
{
private int skillRange = 200;
public string Name { get; set; }
public int Skill { get; set; }
public int SkillRange
{
get
{
return skillRange;
}
set
{
if (value >= 200)
skillRange = value;
else
skillRange = 200;
}
}
}
公共类游戏
{
//田地
私人短打球员;
私人团队轴心;
私人团队盟友;
//性质
公共字符串名称{get;set;}
公共短线球员
{
得到
{
返回最大玩家;
}
设置
{
如果(值>8)
maxPlayers=8;
否则如果(值<2)
maxPlayers=2;
其他的
最大玩家=价值;
}
}
公共短波播放器
{
得到
{
int players=axis.players.Count+友军.players.Count;
返回(短)球员;
}
}
公共图书馆满了
{
得到
{
如果(CurrentPlayer==MaxPlayer)
返回true;
其他的
返回false;
}
}
公共团队轴{get;set;}
公共团队盟友{get;set;}
公开球员名单
{
//不知何故,这也不起作用,所以我不得不在for-each循环中坚持一个团队。要解决的问题?
得到
{
如果(allies.Players.Count==0)
return axis.Players.Concat(allians.Players.ToList();
其他的
返回盟友.Players.Concat(axis.Players.ToList();
}
}
//建造师
公共游戏()
{
axis=新团队();
联盟=新团队();
}
}
公开课小组
{
公共列表玩家{get;set;}
公共EFaction{get;set;}
公共枚举作用
{
盟友,,
轴
随机的
}
公共团队()
{
Players=新列表();
派系=EFaction.Random;
}
}
公开课选手
{
私人智力技能范围=200;
公共字符串名称{get;set;}
公共int技能{get;set;}
公共int技能范围
{
得到
{
返回技能范围;
}
设置
{
如果(值>=200)
skillRange=值;
其他的
技能范围=200;
}
}
}
在启动时,我从数据库填充列表,并对列表执行相同的操作。我想做的是遍历游戏列表,并将游戏中每个玩家的技能属性与团队中每个玩家的技能属性进行比较。下面是我使用的每个循环的示例。这起作用了。但是你可以清楚地看到为什么我这么想把它砍掉
// Loop through each player in the Automatch queue.
foreach (Team team in match.TeamsInQueue)
{
// Loop through every game in the Atomatch queue.
foreach (Game game in match.AvailableGames)
{
int teamPlayersInSkillRange = 0;
// Loop through every player in the team and loop through every player in the game.
foreach (Player teamPlayer in team.Players)
{
int gamePlayersInSkillRange = 0;
foreach (Player gamePlayer in game.Allies.Players)
{
// Compare beoth skill values. If they are in a certain range increase the counter.
if (Math.Abs(teamPlayer.Skill - gamePlayer.Skill) <= 200) // The range is currently set for 200, but I want to make it variable later.
gamePlayersInSkillRange++;
}
// Check if the player in the team is in skill range of the game he wants to join. If yes increase the counter.
if (gamePlayersInSkillRange == game.Allies.Players.Count)
teamPlayersInSkillRange++;
}
// Check if the whole team is in skill range of the game they want to join. If yes return true.
if (teamPlayersInSkillRange == team.Players.Count)
{
// ToDo: Implement join process here.
}
}
}
//循环遍历Automatch队列中的每个播放器。
foreach(比赛中的团队。团队队列)
{
//循环遍历Atomatch队列中的每个游戏。
foreach(比赛中的游戏。可用)
{
int teamPlayersInSkillRange=0;
//通过团队中的每个球员循环,并通过游戏中的每个球员循环。
foreach(队员团队中的队员。队员)
{
int gamePlayersInSkillRange=0;
foreach(游戏中的玩家。盟友。玩家)
{
//比较两个技能值。如果它们在一定范围内,增加计数器。
如果(Math.Abs(teamPlayer.Skill-gamePlayer.Skill)尝试以下方法:
foreach(Team team in match.TeamsInQueue)
{
if(team.Players.Insersect(match
.SelectMany(m => m.AvailableGames, g=> g.Allies.Players),
new PlayerSkillComparer().Count() == team.Players.Count()) {
// ToDO: Implement join process here.
}
}
其中PlayerSkillComparer
实现IEqualityComparer
且其Equals
方法返回true如果给定的两个Player
对象对于给定的团队和游戏有技能差异,则如果团队的所有玩家都在游戏所有玩家的技能范围内,您希望该团队加入游戏。Th这听起来像是一个工作的方法
这计算满足条件的玩家数量,这些玩家可以重构为Count()
调用:
int gamePlayersInSkillRange = game.Allies.Players.Count(g =>
(Math.Abs(teamPlayer.Skill - g.Skill) <= 200);
}
现在这个循环看起来可以重构为Count()
调用。但是如果我们仔细检查之后的代码,我们会发现它与我们刚才重构的循环模式完全相同,这意味着我们可以直接将其重构为All())
调用,完成重构。我总是发现,在将这样的东西转换为LINQ时,从小处着手是最容易的。首先,将最内部的foreach循环转换为LINQ,然后向外移动,直到您满意为止。这很有魅力。除此之外,还有一个精彩的解释,说明如何实现这一点。
int gamePlayersInSkillRange = 0;
foreach (Player gamePlayer in game.Allies.Players)
{
// Compare beoth skill values. If they are in a certain range increase the counter.
if (Math.Abs(teamPlayer.Skill - gamePlayer.Skill) <= 200) // The range is currently set for 200, but I want to make it variable later.
gamePlayersInSkillRange++;
}
int gamePlayersInSkillRange = game.Allies.Players.Count(g =>
(Math.Abs(teamPlayer.Skill - g.Skill) <= 200);
foreach (Player teamPlayer in team.Players)
{
bool allGamePlayersInRange = game.Allies.Players.All(g =>
(Math.Abs(teamPlayer.Skill - g.Skill) <= 200);
// Check if the player in the team is in skill range of the game he wants to join. If yes increase the counter.
if (allGamePlayersInRange)
teamPlayersInSkillRange++;