在 for 循环中调用具有相似名称的不同列表
Call different list with similar name in a for loop
我有几个带有名称的列表:group1、group2、group3...
我需要一个 for 循环(比如说 for (int i=1; i<=6; i++),现在我检查例如如果我是 1 然后使用 group1,如果我是 2 使用 group2 等......我的问题是,我可以用最后的'i'来调用列表吗?像groupi,当i为1时,它的group1,当i为2时,它的group2等。这是代码:
for (int i = 0; i < groupNum; i++)
{
if (i == 0)
{
foreach (Player p1 in group1)
{
foreach (Player p2 in group1)
{
if (p1 != p2)
{
if (group1.IndexOf(p1) > group1.IndexOf(p2))
{
Game game = new Game(tournamentID, p1.id, p2.id);
game.status = "Pending";
gm.CreateGame(game);
}
}
}
}
}
else if (i == 1)
{
foreach (Player p1 in group2)
{
foreach (Player p2 in group2)
{
if (p1 != p2)
{
if (group2.IndexOf(p1) > group2.IndexOf(p2))
{
Game game = new Game(tournamentID, p1.id, p2.id);
game.status = "Pending";
gm.CreateGame(game);
}
}
}
}
}
else if (i == 2)
{
foreach (Player p1 in group3)
{
foreach (Player p2 in group3)
{
if (p1 != p2)
{
if (group3.IndexOf(p1) > group3.IndexOf(p2))
{
Game game = new Game(tournamentID, p1.id, p2.id);
game.status = "Pending";
gm.CreateGame(game);
}
}
}
}
}
else if (i == 3)
{
foreach (Player p1 in group4)
{
foreach (Player p2 in group4)
{
if (p1 != p2)
{
if (group4.IndexOf(p1) > group4.IndexOf(p2))
{
Game game = new Game(tournamentID, p1.id, p2.id);
game.status = "Pending";
gm.CreateGame(game);
}
}
}
}
}
else if (i == 4)
{
foreach (Player p1 in group5)
{
foreach (Player p2 in group5)
{
if (p1 != p2)
{
if (group5.IndexOf(p1) > group5.IndexOf(p2))
{
Game game = new Game(tournamentID, p1.id, p2.id);
game.status = "Pending";
gm.CreateGame(game);
}
}
}
}
}
else if (i == 5)
{
foreach (Player p1 in group6)
{
foreach (Player p2 in group6)
{
if (p1 != p2)
{
if (group6.IndexOf(p1) > group6.IndexOf(p2))
{
Game game = new Game(tournamentID, p1.id, p2.id);
game.status = "Pending";
gm.CreateGame(game);
}
}
}
}
}
如您所见,不同 if 语句的代码实际上是相同的,但唯一的区别在于使用具有相似名称(group1、group2..)的不同列表。
创建群组列表
var groups = new List<Group>(){
group1, group1, group3};
现在你可以做
if(group[i].Indexof.....)
等等
只需将您的组组成一个数组,假设它们在下面 List<Player>
,然后对其进行迭代:
foreach(var grp in new List<Player>[] {group1, group2, group3, group4, group5, group6}) {
foreach (Player p1 in grp)
{
foreach (Player p2 in grp)
{
if (p1 != p2)
{
if (grp.IndexOf(p1) > grp.IndexOf(p2))
{
Game game = new Game(tournamentID, p1.id, p2.id);
game.status = "Pending";
gm.CreateGame(game);
}
}
}
}
}
一般
这经常出现。不;您不能以编程方式构建变量名。编译代码时,变量名无论如何都消失了
如果你的变量名字像
something1
something2
something3
等,那么这是使用数组的候选,但记住数组从 0
开始
var something = new Thing[3];
(在你的例子中,Thing 是一个玩家)
现在您的名字可以有一个固定部分和一个可变部分:
Before you had Now you have
-------------- ------------
something1 something[0]
something2 something[1]
something3 something[2]
数组可以用 for
或 foreach
循环,并且可以像上面那样用硬编码索引随机访问它们。就像您的代码只有 3 个名为 somethingX
的变量一样,您的数组也有固定数量的 3 个值。数组不增长
如果您需要像数组一样工作但会增长的东西,请使用列表:
var something = new List<Thing>();
这是一个 Thing 列表,就像之前您有一个 Thing 数组一样。
另外,不要忘记字典,它们就像列表一样,会增长,但它们可以被任何东西索引,所以你可以通过编程方式建立索引,不像 arrays/lists 那样被索引通过递增整数,字典可以跳过一些索引:
var dict = new Dictionary<int, Thing>();
这意味着“由 int 索引并包含 Thing 的字典”
现在,这是可能的:
dict[1] = new Thing();
dict[2] = new Thing();
dict[4] = new Thing(); //we skipped
键可以是任何东西,例如字符串:
var dict = new Dictionary<string, Thing>();
dict["something1"] = new Thing();
dict["something2"] = new Thing();
dict["sometheng4"] = new Thing(); //watch out for typos!
您可以通过编程方式构建密钥:
int x = 1;
dict["something"+x].SomePropertyOfThing = "Hello";
唯一需要注意的是字典不一定以任何顺序存储它的内容。如果您 foreach
它,您可能会以 something2, sometheng4, something1
顺序输出条目。如果您需要排序,您要么必须对 dict.Keys
进行排序,然后使用它来访问字典,要么根据您的需要使用 SortedDictionary 或 OrderedDictionary
综上所述,这些是我们在 C# 中使用的主要集合类型;他们有不同的长处和短处,在某种情况下选择使用哪一个通常是一个重要的工程决策
最后一点注意事项;在处理集合时尽量使用复数名称,因为它使代码更容易推理
具体在这种情况下
在您的特定情况下,您实际上是在寻找一个数组数组,而一些 LINQ 可能会使您的代码更易于处理:
var groups = new []{ group1, group2, group3 };
foreach(var g in groups)
foreach(var p1 in g)
foreach(var p2 in g.Where(p => p.id > p1.id))
gm.CreateGame(new Game(tournamentID, p1.id, p2.id){status = "Pending"});
如果您只想为特定组 N 举办一场锦标赛,请将 foreach(var g in groups)
替换为 var g = groups[N]
你有这样的逻辑“对于每个玩家 1,对于每个玩家 2,如果他们不是同一个玩家,找到玩家 1 的索引,找到玩家 2 的索引,如果一个索引小于两个索引”包含冗余逻辑,浪费资源寻找它已经找到的东西
说“对于组中的每一个 player1,对于每一个 id 大于 player1 的 player2”就可以解决所有问题。玩家 2 必须与玩家 1 不同,因为他们的 id 更大。无需查找索引;您可以将代码简化为比较 ID,而不是进行 notequals 检查然后查找索引然后比较
如果您的 ID 值由于某种原因在大于意义上本质上不具有可比性(我假设它们是整数),您可以使用更多的 linq 为组中的每个玩家 p 分配一个索引 i:
var groups = new []{
group1.Select((p,i) => (p,i)),
group2.Select((p,i) => (p,i)),
group3.Select((p,i) => (p,i))
};
这会生成玩家的元组以及他们所在的索引,因此可以使用与之前类似的逻辑:
foreach(var g in groups)
foreach(var p1t in g)
foreach(var p2t in g.Where(pt => pt.i > p1t.i))
gm.CreateGame(new Game(tournamentID, p1t.p.id, p2t.p.id){status = "Pending"});
这次 Where 要求玩家 2 的索引 i 更大
您应该使用 PascalCase 命名您的属性,而不是 camelCase
如前所述,您可以将所有组收集在一个数组中,然后遍历该组数组:
List<Player>[] groups = new[] { group1, group2, group3, group4, group5, group6 };
foreach (var group in groups)
{
// play games
}
我也想建议简化您的逻辑。您可以使用更少的嵌套循环来实现相同的结果,只需在每个组中循环 player 1 和 player 2 的必要组合。
一种方法是:
- 遍历玩家列表索引而不是列表中的
Player
对象(即将嵌套 foreach (Player p*)
循环替换为嵌套 for (int i*)
(玩家索引)循环)
- 让外层循环(遍历 玩家 1 的索引)从
0
迭代当前组到 second-to-last-index
- 让内部循环(遍历 玩家 2 的索引)从 一个比 [=51= 的索引大的索引遍历当前组]玩家1到最后一个索引
实施:
foreach (var group in groups)
{
for (int i1 = 0; i1 < group.Count - 1; i1++)
{
Player p1 = group[i1];
for (int i2 = i1 + 1; i2 < group.Count; i2++)
{
Player p2 = group[i2];
Game game = new Game(tournamentID, p1.id, p2.id);
game.status = "Pending";
gm.CreateGame(game);
}
}
}
如果我们将 player 1 的索引简单地称为 1 而 player 2 简单地表示为 2,包含四个玩家的组的迭代可以可视化如下:
1 2 _ _
1 _ 2 _
1 _ _ 2
_ 1 2 _
_ 1 _ 2
_ _ 1 2
如果您更希望按照与原始 post 完全相同的玩家组合顺序创建游戏,则需要更改索引条件,以便 p2
始终出现在组中 p1
之前:
2 1 _ _
2 _ 1 _
_ 2 1 _
2 _ _ 1
_ 2 _ 1
_ _ 2 1
这可以通过稍微改变 for loop
语句来实现:
- 玩家 1 的索引从
1
到组中的最后一个索引
- 玩家 2 的索引从
0
变为 比 玩家 1[=72] 小一个索引=]
foreach (var group in groups)
{
for (var i1 = 1; i1 < group.Count; i1++)
{
//
for (var i2 = 0; i2 < i1; i2++)
{
//
}
}
}
为确保您不会尝试对任何组执行无效循环,您可以更改 foreach
语句以考虑每个组的长度;通过使用 System.Linq 命名空间中的 .Skip(1).Any()
:
//using System.Linq;
foreach (var group in groups.Where(gr => gr.Skip(1).Any()))
{
// play games
}
或计算每组中的项目数:
foreach (var group in groups.Where(gr => gr.Count > 1))
{
// play games
}
我们正在检查每组中的项目数是否大于 1(即项目数至少为 2),因为我们想同时与两个玩家玩游戏。
我有几个带有名称的列表:group1、group2、group3... 我需要一个 for 循环(比如说 for (int i=1; i<=6; i++),现在我检查例如如果我是 1 然后使用 group1,如果我是 2 使用 group2 等......我的问题是,我可以用最后的'i'来调用列表吗?像groupi,当i为1时,它的group1,当i为2时,它的group2等。这是代码:
for (int i = 0; i < groupNum; i++)
{
if (i == 0)
{
foreach (Player p1 in group1)
{
foreach (Player p2 in group1)
{
if (p1 != p2)
{
if (group1.IndexOf(p1) > group1.IndexOf(p2))
{
Game game = new Game(tournamentID, p1.id, p2.id);
game.status = "Pending";
gm.CreateGame(game);
}
}
}
}
}
else if (i == 1)
{
foreach (Player p1 in group2)
{
foreach (Player p2 in group2)
{
if (p1 != p2)
{
if (group2.IndexOf(p1) > group2.IndexOf(p2))
{
Game game = new Game(tournamentID, p1.id, p2.id);
game.status = "Pending";
gm.CreateGame(game);
}
}
}
}
}
else if (i == 2)
{
foreach (Player p1 in group3)
{
foreach (Player p2 in group3)
{
if (p1 != p2)
{
if (group3.IndexOf(p1) > group3.IndexOf(p2))
{
Game game = new Game(tournamentID, p1.id, p2.id);
game.status = "Pending";
gm.CreateGame(game);
}
}
}
}
}
else if (i == 3)
{
foreach (Player p1 in group4)
{
foreach (Player p2 in group4)
{
if (p1 != p2)
{
if (group4.IndexOf(p1) > group4.IndexOf(p2))
{
Game game = new Game(tournamentID, p1.id, p2.id);
game.status = "Pending";
gm.CreateGame(game);
}
}
}
}
}
else if (i == 4)
{
foreach (Player p1 in group5)
{
foreach (Player p2 in group5)
{
if (p1 != p2)
{
if (group5.IndexOf(p1) > group5.IndexOf(p2))
{
Game game = new Game(tournamentID, p1.id, p2.id);
game.status = "Pending";
gm.CreateGame(game);
}
}
}
}
}
else if (i == 5)
{
foreach (Player p1 in group6)
{
foreach (Player p2 in group6)
{
if (p1 != p2)
{
if (group6.IndexOf(p1) > group6.IndexOf(p2))
{
Game game = new Game(tournamentID, p1.id, p2.id);
game.status = "Pending";
gm.CreateGame(game);
}
}
}
}
}
如您所见,不同 if 语句的代码实际上是相同的,但唯一的区别在于使用具有相似名称(group1、group2..)的不同列表。
创建群组列表
var groups = new List<Group>(){
group1, group1, group3};
现在你可以做
if(group[i].Indexof.....)
等等
只需将您的组组成一个数组,假设它们在下面 List<Player>
,然后对其进行迭代:
foreach(var grp in new List<Player>[] {group1, group2, group3, group4, group5, group6}) {
foreach (Player p1 in grp)
{
foreach (Player p2 in grp)
{
if (p1 != p2)
{
if (grp.IndexOf(p1) > grp.IndexOf(p2))
{
Game game = new Game(tournamentID, p1.id, p2.id);
game.status = "Pending";
gm.CreateGame(game);
}
}
}
}
}
一般
这经常出现。不;您不能以编程方式构建变量名。编译代码时,变量名无论如何都消失了
如果你的变量名字像
something1
something2
something3
等,那么这是使用数组的候选,但记住数组从 0
开始var something = new Thing[3];
(在你的例子中,Thing 是一个玩家)
现在您的名字可以有一个固定部分和一个可变部分:
Before you had Now you have
-------------- ------------
something1 something[0]
something2 something[1]
something3 something[2]
数组可以用 for
或 foreach
循环,并且可以像上面那样用硬编码索引随机访问它们。就像您的代码只有 3 个名为 somethingX
的变量一样,您的数组也有固定数量的 3 个值。数组不增长
如果您需要像数组一样工作但会增长的东西,请使用列表:
var something = new List<Thing>();
这是一个 Thing 列表,就像之前您有一个 Thing 数组一样。
另外,不要忘记字典,它们就像列表一样,会增长,但它们可以被任何东西索引,所以你可以通过编程方式建立索引,不像 arrays/lists 那样被索引通过递增整数,字典可以跳过一些索引:
var dict = new Dictionary<int, Thing>();
这意味着“由 int 索引并包含 Thing 的字典”
现在,这是可能的:
dict[1] = new Thing();
dict[2] = new Thing();
dict[4] = new Thing(); //we skipped
键可以是任何东西,例如字符串:
var dict = new Dictionary<string, Thing>();
dict["something1"] = new Thing();
dict["something2"] = new Thing();
dict["sometheng4"] = new Thing(); //watch out for typos!
您可以通过编程方式构建密钥:
int x = 1;
dict["something"+x].SomePropertyOfThing = "Hello";
唯一需要注意的是字典不一定以任何顺序存储它的内容。如果您 foreach
它,您可能会以 something2, sometheng4, something1
顺序输出条目。如果您需要排序,您要么必须对 dict.Keys
进行排序,然后使用它来访问字典,要么根据您的需要使用 SortedDictionary 或 OrderedDictionary
综上所述,这些是我们在 C# 中使用的主要集合类型;他们有不同的长处和短处,在某种情况下选择使用哪一个通常是一个重要的工程决策
最后一点注意事项;在处理集合时尽量使用复数名称,因为它使代码更容易推理
具体在这种情况下
在您的特定情况下,您实际上是在寻找一个数组数组,而一些 LINQ 可能会使您的代码更易于处理:
var groups = new []{ group1, group2, group3 };
foreach(var g in groups)
foreach(var p1 in g)
foreach(var p2 in g.Where(p => p.id > p1.id))
gm.CreateGame(new Game(tournamentID, p1.id, p2.id){status = "Pending"});
如果您只想为特定组 N 举办一场锦标赛,请将 foreach(var g in groups)
替换为 var g = groups[N]
你有这样的逻辑“对于每个玩家 1,对于每个玩家 2,如果他们不是同一个玩家,找到玩家 1 的索引,找到玩家 2 的索引,如果一个索引小于两个索引”包含冗余逻辑,浪费资源寻找它已经找到的东西
说“对于组中的每一个 player1,对于每一个 id 大于 player1 的 player2”就可以解决所有问题。玩家 2 必须与玩家 1 不同,因为他们的 id 更大。无需查找索引;您可以将代码简化为比较 ID,而不是进行 notequals 检查然后查找索引然后比较
如果您的 ID 值由于某种原因在大于意义上本质上不具有可比性(我假设它们是整数),您可以使用更多的 linq 为组中的每个玩家 p 分配一个索引 i:
var groups = new []{
group1.Select((p,i) => (p,i)),
group2.Select((p,i) => (p,i)),
group3.Select((p,i) => (p,i))
};
这会生成玩家的元组以及他们所在的索引,因此可以使用与之前类似的逻辑:
foreach(var g in groups)
foreach(var p1t in g)
foreach(var p2t in g.Where(pt => pt.i > p1t.i))
gm.CreateGame(new Game(tournamentID, p1t.p.id, p2t.p.id){status = "Pending"});
这次 Where 要求玩家 2 的索引 i 更大
您应该使用 PascalCase 命名您的属性,而不是 camelCase
如前所述,您可以将所有组收集在一个数组中,然后遍历该组数组:
List<Player>[] groups = new[] { group1, group2, group3, group4, group5, group6 };
foreach (var group in groups)
{
// play games
}
我也想建议简化您的逻辑。您可以使用更少的嵌套循环来实现相同的结果,只需在每个组中循环 player 1 和 player 2 的必要组合。
一种方法是:
- 遍历玩家列表索引而不是列表中的
Player
对象(即将嵌套foreach (Player p*)
循环替换为嵌套for (int i*)
(玩家索引)循环) - 让外层循环(遍历 玩家 1 的索引)从
0
迭代当前组到 second-to-last-index - 让内部循环(遍历 玩家 2 的索引)从 一个比 [=51= 的索引大的索引遍历当前组]玩家1到最后一个索引
实施:
foreach (var group in groups)
{
for (int i1 = 0; i1 < group.Count - 1; i1++)
{
Player p1 = group[i1];
for (int i2 = i1 + 1; i2 < group.Count; i2++)
{
Player p2 = group[i2];
Game game = new Game(tournamentID, p1.id, p2.id);
game.status = "Pending";
gm.CreateGame(game);
}
}
}
如果我们将 player 1 的索引简单地称为 1 而 player 2 简单地表示为 2,包含四个玩家的组的迭代可以可视化如下:
1 2 _ _
1 _ 2 _
1 _ _ 2
_ 1 2 _
_ 1 _ 2
_ _ 1 2
如果您更希望按照与原始 post 完全相同的玩家组合顺序创建游戏,则需要更改索引条件,以便 p2
始终出现在组中 p1
之前:
2 1 _ _
2 _ 1 _
_ 2 1 _
2 _ _ 1
_ 2 _ 1
_ _ 2 1
这可以通过稍微改变 for loop
语句来实现:
- 玩家 1 的索引从
1
到组中的最后一个索引 - 玩家 2 的索引从
0
变为 比 玩家 1[=72] 小一个索引=]
foreach (var group in groups)
{
for (var i1 = 1; i1 < group.Count; i1++)
{
//
for (var i2 = 0; i2 < i1; i2++)
{
//
}
}
}
为确保您不会尝试对任何组执行无效循环,您可以更改 foreach
语句以考虑每个组的长度;通过使用 System.Linq 命名空间中的 .Skip(1).Any()
:
//using System.Linq;
foreach (var group in groups.Where(gr => gr.Skip(1).Any()))
{
// play games
}
或计算每组中的项目数:
foreach (var group in groups.Where(gr => gr.Count > 1))
{
// play games
}
我们正在检查每组中的项目数是否大于 1(即项目数至少为 2),因为我们想同时与两个玩家玩游戏。