递归列表处理似乎在更高级别更改列表
recursive list processing seems to be changing the list at higher levels
我正在尝试编写一个竞争配对算法来避免同一个玩家玩两次
所以我们有一个玩家列表
我们取第一个玩家,然后是第一个他们没有玩过的玩家
从列表中删除
发送剩余的列表重新处理
如果最后一对不能玩,递归应该展开,第一个玩家与下一个他们没有玩过的玩家匹配,然后我们再去。
似乎正在发生的事情是原始列表(玩家)随着通过递归调用发送的截断列表的大小发生变化。
所以当 reucrsion 展开时,玩家列表减少到 2 个项目而不是预期的 4 或 6 个。这就像列表是通过引用而不是通过值传递的。
有什么想法吗?
编辑***
与其说是通过引用传递的列表,不如说是列表(玩家)在每次调用该过程时都会发生变化,所以我们最终得到了该过程的第一次迭代(应该有一个包含 6 名玩家的列表) 在递归展开时使用 2 个玩家的列表 ***
我把整个代码都放在这里(连同测试列表设置代码)
using System;
using System.Collections.Generic;
using System.Runtime.ConstrainedExecution;
namespace CPair
{
class Program
{
static void Main(string[] args)
{
//create players
List<int> alist = new List<int>() { 2 };
var a = new Player(1, "a", "wk", alist, 10);
List<int> blist = new List<int>() { 1 };
var b = new Player(2, "b", "wa", blist, 9);
List<int> clist = new List<int>() { };
var c = new Player(3, "c", "bc", clist, 8);
List<int> dlist = new List<int>() { };
var d = new Player(4, "d", "wk", dlist, 7);
List<int> elist = new List<int>() { };
var e = new Player(5, "e", "bc", elist, 5);
List<int> flist = new List<int>() { };
var f = new Player(6, "f", "ab", flist, 3);
List<Player> PlayList = new List<Player>();
PlayList.Add(a);
PlayList.Add(b);
PlayList.Add(c);
PlayList.Add(d);
PlayList.Add(e);
PlayList.Add(f);
PlayList.Sort((p, q) => p.Points.CompareTo(q.Points));
foreach (Player p in PlayList)
{
Console.WriteLine(p.PlayerName);
}
List<Player> paired = new List<Player>();
paired = pairing(PlayList);
foreach (Player r in paired)
{
Console.WriteLine(r.PlayerName);
}
}
static List<Player> pairing(List<Player> players)
{
List<Player> pairingList = new List<Player>();
int n = 1;
bool failed = true;
List<Player> returnedList = new List<Player>();
while ((failed) && n <= players.Count - 1)
{
if (PairIsGood(players[0], players[n], 0))
{
Player p1 = new Player();
p1 = players[0];
Player p2 = new Player();
p2 = players[n];
if (players.Count <= 2)
{
returnedList.Add(p1);
returnedList.Add(p2);
failed = false;
}
else
{
List<Player> nextPairs = new List<Player>();
nextPairs = players;
nextPairs.RemoveAt(0);
nextPairs.RemoveAt(n-1);
returnedList = pairing(nextPairs);
Console.WriteLine(players.Count.ToString());
Console.WriteLine(nextPairs.Count.ToString());
if (returnedList.Count == 0)
{
failed = true;
n++;
}
else
{
returnedList.Add(p1);
returnedList.Add(p2);
failed = false;
}
}
}
else
{
n++;
}
}
return returnedList;
}
static bool PairIsGood(Player p1, Player p2, int round)
{
bool good = true;
foreach (int op in p1.OpList)
{
if (op == p2.PlayerID)
{
good = false;
}
}
return good;
}
}
}
这是你的问题:
List<Player> nextPairs = new List<Player>();
nextPairs = players;
nextPairs.RemoveAt(0);
nextPairs.RemoveAt(n-1);
您创建一个新的 List<Player>
并将其分配给 nextPairs
然后您有效地丢弃了那个新列表,而是将 nextPairs
分配给 players
。
nextPairs
和 players
现在都引用同一个列表,从 nextPairs
中删除也会从 players
中删除,因为它们是同一个列表。
如果你想要真正的独立副本,请查看Array.Copy()
。
顺便说一句,我看到你在这里做同样的冗余创建模式:
Player p1 = new Player();
p1 = players[0];
Player p2 = new Player();
p2 = players[n];
这应该只是
Player p1 = players[0];
Player p2 = players[n];
我怀疑您需要阅读一些关于对象和引用以及它们如何工作的内容。
我正在尝试编写一个竞争配对算法来避免同一个玩家玩两次
所以我们有一个玩家列表
我们取第一个玩家,然后是第一个他们没有玩过的玩家
从列表中删除
发送剩余的列表重新处理
如果最后一对不能玩,递归应该展开,第一个玩家与下一个他们没有玩过的玩家匹配,然后我们再去。
似乎正在发生的事情是原始列表(玩家)随着通过递归调用发送的截断列表的大小发生变化。
所以当 reucrsion 展开时,玩家列表减少到 2 个项目而不是预期的 4 或 6 个。这就像列表是通过引用而不是通过值传递的。
有什么想法吗?
编辑***
与其说是通过引用传递的列表,不如说是列表(玩家)在每次调用该过程时都会发生变化,所以我们最终得到了该过程的第一次迭代(应该有一个包含 6 名玩家的列表) 在递归展开时使用 2 个玩家的列表 ***
我把整个代码都放在这里(连同测试列表设置代码)
using System;
using System.Collections.Generic;
using System.Runtime.ConstrainedExecution;
namespace CPair
{
class Program
{
static void Main(string[] args)
{
//create players
List<int> alist = new List<int>() { 2 };
var a = new Player(1, "a", "wk", alist, 10);
List<int> blist = new List<int>() { 1 };
var b = new Player(2, "b", "wa", blist, 9);
List<int> clist = new List<int>() { };
var c = new Player(3, "c", "bc", clist, 8);
List<int> dlist = new List<int>() { };
var d = new Player(4, "d", "wk", dlist, 7);
List<int> elist = new List<int>() { };
var e = new Player(5, "e", "bc", elist, 5);
List<int> flist = new List<int>() { };
var f = new Player(6, "f", "ab", flist, 3);
List<Player> PlayList = new List<Player>();
PlayList.Add(a);
PlayList.Add(b);
PlayList.Add(c);
PlayList.Add(d);
PlayList.Add(e);
PlayList.Add(f);
PlayList.Sort((p, q) => p.Points.CompareTo(q.Points));
foreach (Player p in PlayList)
{
Console.WriteLine(p.PlayerName);
}
List<Player> paired = new List<Player>();
paired = pairing(PlayList);
foreach (Player r in paired)
{
Console.WriteLine(r.PlayerName);
}
}
static List<Player> pairing(List<Player> players)
{
List<Player> pairingList = new List<Player>();
int n = 1;
bool failed = true;
List<Player> returnedList = new List<Player>();
while ((failed) && n <= players.Count - 1)
{
if (PairIsGood(players[0], players[n], 0))
{
Player p1 = new Player();
p1 = players[0];
Player p2 = new Player();
p2 = players[n];
if (players.Count <= 2)
{
returnedList.Add(p1);
returnedList.Add(p2);
failed = false;
}
else
{
List<Player> nextPairs = new List<Player>();
nextPairs = players;
nextPairs.RemoveAt(0);
nextPairs.RemoveAt(n-1);
returnedList = pairing(nextPairs);
Console.WriteLine(players.Count.ToString());
Console.WriteLine(nextPairs.Count.ToString());
if (returnedList.Count == 0)
{
failed = true;
n++;
}
else
{
returnedList.Add(p1);
returnedList.Add(p2);
failed = false;
}
}
}
else
{
n++;
}
}
return returnedList;
}
static bool PairIsGood(Player p1, Player p2, int round)
{
bool good = true;
foreach (int op in p1.OpList)
{
if (op == p2.PlayerID)
{
good = false;
}
}
return good;
}
}
}
这是你的问题:
List<Player> nextPairs = new List<Player>();
nextPairs = players;
nextPairs.RemoveAt(0);
nextPairs.RemoveAt(n-1);
您创建一个新的 List<Player>
并将其分配给 nextPairs
然后您有效地丢弃了那个新列表,而是将 nextPairs
分配给 players
。
nextPairs
和 players
现在都引用同一个列表,从 nextPairs
中删除也会从 players
中删除,因为它们是同一个列表。
如果你想要真正的独立副本,请查看Array.Copy()
。
顺便说一句,我看到你在这里做同样的冗余创建模式:
Player p1 = new Player();
p1 = players[0];
Player p2 = new Player();
p2 = players[n];
这应该只是
Player p1 = players[0];
Player p2 = players[n];
我怀疑您需要阅读一些关于对象和引用以及它们如何工作的内容。