我有问题。我正在为一个学校项目制作一个网球锦标赛计划。我们应该使用txt文件,在那里他们正在阅读我们需要能够提取一定数量的玩家,这将用于模拟锦标赛。
public class ReadPlayers
{
private List<ReadFiles> players = new List<ReadFiles>(); //Opretter en liste af strenge.
public string FileName { get; set; }
public string Delimiter { get; set; }
public ReadPlayers(string fn, string delim = "|") //Konstruktur
{
FileName = fn;
Delimiter = delim;
}
public override string ToString()
{
var rv = "";
foreach (var c in players)
rv += c + "\n";
return rv;
}
public void Load()
{
TextFieldParser par = new TextFieldParser(FileName, Encoding.GetEncoding("iso-8859-1"));
par.TextFieldType = FieldType.Delimited;
par.SetDelimiters(Delimiter);
while (!par.EndOfData)
{
string[] fields = par.ReadFields();
string FirstName = fields[1];
string MiddleName = fields[2];
string LastName = fields[3];
DateTime DateOfBirth = DateTime.ParseExact(fields[4], "yyyy-MM-dd", CultureInfo.InvariantCulture);
String Country = fields[5];
string ShortNameCountry = fields[6];
var c = new ReadFiles(FirstName, MiddleName, LastName, DateOfBirth, Country, ShortNameCountry);
players.Add(c);
}
players.Shuffle();
par.Close();
在我的主要内容中,我加载文件并打印出来。这非常有效。但是我需要能够从列表中仅打印8,16,32或64个玩家。
答案 0 :(得分:1)
您可以使用所谓的"Reservoir sampling"从未知长度的序列中选择指定数量的项目(但必须足够长以提供所有项目)。
算法如下所示:
public static T[] RandomlySelectedItems<T>(IEnumerable<T> items, int n, Random rng)
{
var result = new T[n];
int index = 0;
int count = 0;
foreach (var item in items)
{
if (index < n)
{
result[count++] = item;
}
else
{
int r = rng.Next(0, index + 1);
if (r < n)
result[r] = item;
}
++index;
}
if (index < n)
throw new ArgumentException("Input sequence too short");
return result;
}
请注意,生成的数组是随机顺序;它不包含它们在输入序列中出现的顺序。
您可以使用它从文本文件中随机选择N行(并以随机顺序),如下所示:
string filename = "Your filename goes here";
var lines = File.ReadLines(filename);
int n = 16; // Number of lines to select.
var result = RandomlySelectedItems(lines, n, new Random()).ToList();
答案 1 :(得分:0)
有办法做到这一点。
MAX_PLAYERS
)或一个变量来存储你想要的玩家的Max_Count,即8,16,32或64.声明一个计数器并在while循环中递增它。一旦到达计数器退出循环。在这里,您将只获得您感兴趣的前8个或16个玩家表格。当所有记录不感兴趣时,不需要阅读完整档案。 while (!par.EndOfData && counter < MAX_PLAYERS)
players.Shuffle();
语句。因此,在洗牌后从列表中选择顶部MAX_PLAYERS
。这样更合乎逻辑,因为您保留了完整的玩家列表以及所选择的列表。 var selectedList = players.Take(MAX_PLAYERS);
答案 2 :(得分:0)
您可以更改ToString()方法以接收两个参数
第一个是你想要在字符串中返回的玩家数量,第二个参数是在获得下一批玩家之前从列表中跳过的玩家数量。
public string ToString(int takeCount, int skipFirst)
{
return string.Join(Environment.NewLine, players.Skip(skipFirst).Take(takeCount));
}
还添加一个属性,告诉您列表中有多少玩家
public int NumberOfPlayers
{
get { return players.Count; }
}
通过这种方式,您可以在循环内调用ToString并接收批量玩家,直到达到列表中的玩家总数
int batchSize = 16;
for(int i = 0; i < readPlayerInstance.NumberOfPlayers; i+=batchSize)
{
string players = readPlayerInstance.ToString(batchSize, i)
.... show your players in batch of 16
}
当然,您不必更改ToString()方法的覆盖,只需添加自己的方法,以您喜欢的方式批量返回玩家,并(例如)返回玩家的子列表。
public List<ReadFiles> GetPlayers(int takeCount, int skipFirst)
{
return players.Skip(skipFirst).Take(takeCount).ToList();
}