从列表中的 txt 文件中获取一定数量的行。
Get an certain number of lines from a txt file in a list.
我有问题。我正在为学校项目制作网球锦标赛程序。我们应该使用 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 名球员。
有很多方法可以做到。
- 声明一个常量 (
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);
您可以更改 ToString() 方法以接收两个参数
第一个是你想要在字符串中 return 的玩家数量,第二个参数是在获得下一批玩家之前要从列表中跳过的玩家数量。
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() 方法的重写,只需添加您自己的方法即可 return 以您喜欢的方式分批播放玩家并且(例如)return 你的玩家的子列表。
public List<ReadFiles> GetPlayers(int takeCount, int skipFirst)
{
return players.Skip(skipFirst).Take(takeCount).ToList();
}
您可以使用所谓的 "Reservoir sampling" 来 select 来自未知长度序列的指定数量的项目(但必须足够长以提供所有项目)。
算法如下所示:
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;
}
请注意,生成的数组是随机排列的;它不包含元素在输入序列中出现的顺序。
您可以使用它从文本文件中随机 select 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();
我有问题。我正在为学校项目制作网球锦标赛程序。我们应该使用 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 名球员。
有很多方法可以做到。
- 声明一个常量 (
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);
您可以更改 ToString() 方法以接收两个参数
第一个是你想要在字符串中 return 的玩家数量,第二个参数是在获得下一批玩家之前要从列表中跳过的玩家数量。
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() 方法的重写,只需添加您自己的方法即可 return 以您喜欢的方式分批播放玩家并且(例如)return 你的玩家的子列表。
public List<ReadFiles> GetPlayers(int takeCount, int skipFirst)
{
return players.Skip(skipFirst).Take(takeCount).ToList();
}
您可以使用所谓的 "Reservoir sampling" 来 select 来自未知长度序列的指定数量的项目(但必须足够长以提供所有项目)。
算法如下所示:
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;
}
请注意,生成的数组是随机排列的;它不包含元素在输入序列中出现的顺序。
您可以使用它从文本文件中随机 select 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();