我有一系列玩家(字符串[]),现在我需要获得一组代表游戏(playerN-playerM)的对象来组织锦标赛表,如下图所示:
期望的最终结果是生成一个包含所有需要播放的游戏的灯具列表。
如何以高效的方式使用LINQ做到这一点?
更新: A-B,A-C,A-D不正确 - 游戏应该能够并行运行。 我需要的结果与图片中的顺序相同
答案 0 :(得分:5)
以下代码可用于为一组球队生成一个夹具列表,以确保每次在1个主场和1场客场比赛中比赛所有其他球队。
代码有点冗长,但它可以按照您指定的顺序为您提供一个列表。
代码可能会被优化,但目前这是我的头脑。
注意:结果列表将包含Home和Away夹具,根据您的网格,您将无论如何都需要做。
class Fixture
{
public string Home { get; set; }
public string Away { get; set; }
}
void CallCode()
{
string players = new string[] { "A", "B", "C", "D" };
List<Fixture> fixtures = CalculateFixtures(players);
}
List<Fixture> CalculateFixtures(string[] players)
{
//create a list of all possible fixtures (order not important)
List<Fixture> fixtures = new List<Fixture>();
for (int i = 0; i < players.Length; i++)
{
for (int j = 0; j < players.Length; j++)
{
if (players[i] != players[j])
{
fixtures.Add(new Fixture() { Home = players[i], Away = players[j] });
}
}
}
fixtures.Reverse();//reverse the fixture list as we are going to remove element from this and will therefore have to start at the end
//calculate the number of game weeks and the number of games per week
int gameweeks = (players.Length - 1) * 2;
int gamesPerWeek = gameweeks / 2;
List<Fixture> sortedFixtures = new List<Fixture>();
//foreach game week get all available fixture for that week and add to sorted list
for (int i = 0; i < gameweeks; i++)
{
sortedFixtures.AddRange(TakeUnique(fixtures, gamesPerWeek));
}
return sortedFixtures;
}
List<Fixture> TakeUnique(List<Fixture> fixtures, int gamesPerWeek)
{
List<Fixture> result = new List<Fixture>();
//pull enough fixture to cater for the number of game to play
for (int i = 0; i < gamesPerWeek; i++)
{
//loop all fixture to find an unused set of teams
for (int j = fixtures.Count - 1; j >= 0; j--)
{
//check to see if any teams in current fixtue have already been used this game week and ignore if they have
if (!result.Any(r => r.Home == fixtures[j].Home || r.Away == fixtures[j].Home || r.Home == fixtures[j].Away || r.Away == fixtures[j].Away))
{
//teams not yet used
result.Add(fixtures[j]);
fixtures.RemoveAt(j);
}
}
}
return result;
}
答案 1 :(得分:4)
var games = players.SelectMany((player1, index) =>
players.Skip(index + 1).
Select(player2 => new {Player1 = player1, Player2 = player2}));
应该这样做......
答案 2 :(得分:1)
我真正想要的实现:
public static List<List<Tuple<string, string>>> ListMatches(List<string> listTeam)
{
var result = new List<List<Tuple<string, string>>>();
int numDays = (listTeam.Count - 1);
int halfSize = listTeam.Count / 2;
var teams = new List<string>();
teams.AddRange(listTeam.Skip(halfSize).Take(halfSize));
teams.AddRange(listTeam.Skip(1).Take(halfSize - 1).ToArray().Reverse());
int teamsSize = teams.Count;
for (int day = 0; day < numDays; day++)
{
var round = new List<Tuple<string, string>>();
int teamIdx = day % teamsSize;
round.Add(new Tuple<string, string>(teams[teamIdx], listTeam[0]));
for (int idx = 1; idx < halfSize; idx++)
{
int firstTeam = (day + idx) % teamsSize;
int secondTeam = (day + teamsSize - idx) % teamsSize;
round.Add(new Tuple<string, string>(teams[firstTeam], teams[secondTeam]));
}
result.Add(round);
}
return result;
}