我正在处理一个项目,我有点困惑。我从我的老师那里得到了一些txt文件(来自his site文件:wt40.txt,wt50.txt,wt100.txt)。
每个文件结构都类似:
26 24 79 46 32 35 73 74 14 67 86 46 78 40 29 94 64 27 90 55
35 52 36 69 85 95 14 78 37 86 44 28 39 12 30 68 70 9 49 50
1 10 9 10 10 4 3 2 10 3 7 3 1 3 10 4 7 7 4 7
5 3 5 4 9 5 2 8 10 4 7 4 9 5 7 7 5 10 1 3
文件wt40.txt应该读作:前两行到第一列,下两行到下一列,第三对到第三列。下一行应该再次与这些列表成对。
在C ++中,我是以这种简单的方式做到的:
for(int ins=0; ins<125; ins++) //125 instances in file
{
for(int i=0; i<N; i++) file>>tasks[i].p; //N elements at two first lines
for(int i=0; i<N; i++) file>>tasks[i].w;
for(int i=0; i<N; i++) file>>tasks[i].d;
tasks[i].putToLists();
}
但是当我在C#中编写它时,我必须打开StreamReader,读取每一行,用regexp拆分它们,将它们转换为int并添加到列表中。这是很多循环。 我无法读取每6个字符并将它们添加到三个循环中,因为那些文本文件已经搞乱了行字符的结尾 - 有时它只是'\ n'有时更多。
有没有更简单的方法?
答案 0 :(得分:1)
基本上有一个20位数的6位数(字符)数字表,带有前导空格。
26 24 79 46 32 35 73 74 14 67 86 46 78 40 29 94 64 27 90 55
35 52 36 69 85 95 14 78 37 86 44 28 39 12 30 68 70 9 49 50
1 10 9 10 10 4 3 2 10 3 7 3 1 3 10 4 7 7 4 7
5 3 5 4 9 5 2 8 10 4 7 4 9 5 7 7 5 10 1 3
我不明白最后一句:
文件wt40.txt应该读作:前两行到第一列,下一行 两行到下一个列表和第三对行到第三列表。下一个 再次将这些行与这些列表成对出现。
假设您想获得前6行并创建3个列表,每个列有2行,您可以这样做:
它渴望将所有内容读入内存然后完成其工作。
const int maxNumberDigitLength = 6;
const int rowLengthInChars = maxNumberDigitLength * 20;
const int totalNumberOfCharsToRead = rowLengthInChars * maxNumberDigitLength;
char[] buffer = new char[totalNumberOfCharsToRead];
using (StreamReader reader = new StreamReader("wt40.txt")
{
int numberOfCharsRead = reader.Read(buffer, 0, totalNumberOfCharsToRead);
}
// put them in your lists
IEnumerable<char> l1 = buffer.Take(rowLengthInChars);
IEnumerable<char> l2 = buffer.Skip(rowLengthInChars).Take(rowLengthInChars);
IEnumerable<char> l3 = buffer.Skip(rowLengthInChars*2).Take(rowLengthInChars);
// Get the list of strings from the list of chars using non LINQ method.
List<string> list1 = new List<string>();
int i = 0;
StringBuilder sb = new StringBuilder();
foreach(char c in l1)
{
if(i < maxNumberDigitLength)
{
sb.Append(c);
i++;
}
i = 0;
list1.Add(sb.ToString());
}
// LINQ method
string s = string.Concat(l1);
List<string> list1 = Enumerable
.Range(0, s.Length / maxNumberDigitLength)
.Select(i => s.Substring(i * maxNumberDigitLength, maxNumberDigitLength))
.ToList();
// Parse to ints using LINQ projection
List<int> numbers1 = list1.Select(int.Parse);
List<int> numbers2 = list2.Select(int.Parse);
List<int> numbers3 = list3.Select(int.Parse);
答案 1 :(得分:1)
还有更简单的方法吗?
不知道它是否更简单,但只有一个循环和一点LINQ
:
List<List<int>> lists = new List<List<int>>();
using (StreamReader reader = new StreamReader("wt40.txt"))
{
string line;
int count = 0;
while ((line = reader.ReadLine()) != null)
{
List<int> currentList =
Regex.Split(line, "\\s")
.Where(s => !string.IsNullOrWhiteSpace(s))
.Select(int.Parse).ToList();
if (currentList.Count > 0) // skip empty lines
{
if (count % 2 == 0) // append each second list to the previous one
{
lists.Add(currentList);
}
else
{
lists[count / 2].AddRange(currentList);
}
}
count++;
}
}
总共最终得到375个列表,每个列表包含40个数字(至少用于wt40.txt
输入)。