使用for循环从数组迭代到列表
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用for循环从数组迭代到列表相关的知识,希望对你有一定的参考价值。
我有一个文本文件,分为许多部分,每个部分大约10行左右。我正在使用File.ReadAllLines将文件读入一个数组,每个元素的一行元素,然后我正在尝试解析文件的每个部分以带回一些数据。我将结果存储在列表中,并希望最终将列表导出到csv。
我的for循环给我带来麻烦,因为它循环了适当的次数,但每次只从文本文件的第一部分提取数据而不是从第一部分提取数据然后继续并拉动数据从下一节开始。我确定我在for循环或每个循环中都做错了。任何帮助我解决这个问题的线索将非常感激!谢谢大卫
我的代码到目前为止:
namespace ParseAndExport
{
class Program
{
static readonly string sourcefile = @"Path";
static void Main(string[] args)
{
string[] readInLines = File.ReadAllLines(sourcefile);
int counter = 0;
int holderCPStart = counter + 3;//Changed Paths will be an different number of lines each time, but will always start 3 lines after the startDiv
/*Need to find the start of the section and the end of the section and parse the bit in between.
* Also need to identify the blank line that occurs in each section as it is essentially a divider too.*/
int startDiv = Array.FindIndex(readInLines, counter, hyphens72);
int blankLine = Array.FindIndex(readInLines, startDiv, emptyElement);
int endDiv = Array.FindIndex(readInLines, counter + 1, hyphens72);
List<string> results = new List<string>();
//Test to see if FindIndexes work. Results should be 0, 7, 9 for 1st section of sourcefile
/*Console.WriteLine(startDiv);
Console.WriteLine(blankLine);
Console.WriteLine(endDiv);*/
//Check how long the file is so that for testing we know how long the while loop should run for
//Console.WriteLine(readInLines.Length);
//sourcefile has 5255 lines (elements) in the array
for (int i = 0; i <= readInLines.Length; i++)
{
if (i == startDiv)
{
results = (readInLines[i + 1].Split('|').Select(p => p.Trim()).ToList());
string holderCP = string.Join(Environment.NewLine, readInLines, holderCPStart, (blankLine - holderCPStart - 1)).Trim();
results.Add(holderCP);
string comment = string.Join(" ", readInLines, blankLine + 1, (endDiv - (blankLine + 1)));//in case the comment is more than one line long
results.Add(comment);
i = i + 1;
}
else
{
i = i + 1;
}
foreach (string result in results)
{
Console.WriteLine(result);
}
//csvcontent.AppendLine("Revision Number, Author, Date, Time, Count of Lines, Changed Paths, Comments");
/* foreach (string result in results)
{
for (int x = 0; x <= results.Count(); x++)
{
StringBuilder csvcontent = new StringBuilder();
csvcontent.AppendLine(results[x] + "," + results[x + 1] + "," + results[x + 2] + "," + results[x + 3] + "," + results[x + 4] + "," + results[x + 5]);
x = x + 6;
string csvpath = @"addressforcsvfile";
File.AppendAllText(csvpath, csvcontent.ToString());
}
}*/
}
Console.ReadKey();
}
private static bool hyphens72(String h)
{
if (h == "------------------------------------------------------------------------")
{
return true;
}
else
{
return false;
}
}
private static bool emptyElement(String ee)
{
if (ee == "")
{
return true;
}
else
{
return false;
}
}
}
}
看起来你试图抓住文件中不是“------”的所有行并将它们放入字符串列表中。
你可以试试这个:
var lineswithoutdashes = readInLines.Where(x => x != hyphens72).Select(x => x).ToList();
现在您可以使用此列表并使用“|”进行拆分提取你想要的字段
逻辑似乎是错误的。代码本身也存在问题。我不确定你究竟想要做什么。无论如何,我希望有一些提示会有所帮助:
- if(i == startDiv)检查我是否等于startDiv。我假设当满足这个条件时发生的逻辑就是你所说的“从第一部分中提取数据”。这是正确的,因为当我等于startDiv时你只运行这段代码。
- 你在for循环中增加了计数器I,这本身也增加了计数器i。
- 如果2.中的问题不存在那么我建议不要在if(i == startDiv)的true和false条件下执行相同的操作“i = i + 1”。
鉴于我认为这个文件实际上可能很大,不建议将它存储在内存中,但只是逐行读取文件并逐行处理。目前没有明显的原因你想要消耗这么多的内存,除非是因为这个API“File.ReadAllLines(sourcefile)”的便利性。我不会太害怕读这样的文件:
Try (BufferedReader br = new BufferedReader(new FileReader (file))) {
String line;
while ((line = br.readLine()) != null) {
// process the line.
}
}
您可以跳过这些行,直到您通过行等于连字符72的位置。
然后对于每一行,使用您在(i == startDiv)的真实情况下提供的代码处理该行,或者至少从您描述的内容处理该行,这是我假设您正在尝试执行的操作。
int startDiv
将返回包含hyphens72
的行号。
因此,您当前的for
循环将仅复制到与计算的行号匹配的单行的结果。
我想你想在当前行搜索startDiv
的位置?
const string hyphens72;
// loop over lines
for (var lineNumber = 0; lineNumber <= readInLines.Length; lineNumber++) {
string currentLine = readInLines[lineNumber];
int startDiv = currentLine.IndexOf(hyphens72);
// loop over characters in line
for (var charIndex = 0; charIndex < currentLine.Length; charIndex++) {
if (charIndex == startDiv) {
var currentCharacter = currentLine[charIndex];
// write to result ...
}
else {
continue; // skip this character
}
}
}
有几件事可以改进。
- 我会在
ReadLines
上使用File.ReadAllLines(
,因为ReadAllLines会读取所有的行。 ReadLines将流式传输它。 - 使用行
results = (readInLines[i + 1].Split('|').Select(p => p.Trim()).ToList());
,您将覆盖之前的结果列表。你最好使用results.AddRange()
来添加新的结果。 for (int i = 0; i <= readInLines.Length; i++)
意味着当长度= 10时,它将进行11次迭代。 (1太多)(删除=
)Array.FindIndex(readInLines, counter, hyphens72);
将进行扫描。在大文件上,完全阅读它们并在其中搜索需要很长时间。尝试仅触摸一行。
我无法测试你在做什么,但这里有一个提示:
IEnumerable<string> readInLines = File.ReadLines(sourcefile);
bool started = false;
List<string> results = new List<string>();
foreach(var line in readInLines)
{
// skip empty lines
if(emptyElement(line))
continue;
// when dashes are found, flip a boolean to activate the reading mode.
if(hyphens72(line))
{
// flip state.. (start/end)
started != started;
}
if(started)
{
// I don't know what you are doing here precisely, do what you gotta do. ;-)
results.AddRange((line.Split('|').Select(p => p.Trim()).ToList()));
string holderCP = string.Join(Environment.NewLine, readInLines, holderCPStart, (blankLine - holderCPStart - 1)).Trim();
results.Add(holderCP);
string comment = string.Join(" ", readInLines, blankLine + 1, (endDiv - (blankLine + 1)));//in case the comment is more than one line long
results.Add(comment);
}
}
foreach (string result in results)
{
Console.WriteLine(result);
}
您可能想要从这样的类开始。我不知道每个部分是以一行连字符开头,还是介于两者之间。这应该处理任何一种情况。
这将是你的巨大的字符串列表(文件中的行)并将其分成块 - 每个块是一组行(根据你的OP,大约10行)。
原因是尝试读取文件,查找连字符以及同时处理文件内容是不必要的复杂。相反,一个类接受输入并将其分成块。就是这样。
另一个类可能会读取该文件并将其内容传递给此类以将其分解。然后输出是单个文本块。
然后,另一个类可以处理10行左右的各个部分,而不必担心连字符或块与其他部分之间的区别。
既然这些类中的每一个都在做自己的事情,那么分别为每个类编写单元测试会更容易。您可以测试您的“处理”类是否接收到大约10行的数组,并执行它应该对它们执行的任何操作。
public class TextSectionsParser
{
private readonly string _delimiter;
public TextSectionsParser(string delimiter)
{
_delimiter = delimiter;
}
public IEnumerable<IEnumerable<string>> ParseSections(IEnumerable<string> lines)
{
var result = new List<List<string>>();
var currentList = new List<string>();
foreach (var line in lines)
{
if (line == _delimiter)
{
if(currentList.Any())
result.Add(currentList);
currentList = new List<string>();
}
else
{
currentList.Add(line);
}
}
if (currentList.Any() && !result.Contains(currentList))
{
result.Add(currentList);
}
return result;
}
}
以上是关于使用for循环从数组迭代到列表的主要内容,如果未能解决你的问题,请参考以下文章
csharp 示例演示如何使用for循环以相反顺序迭代数组。从计算机编程基础知识到C#http:/
迭代 4 个 pandas 数据框列并将它们存储到 4 个列表中,其中一个 for 循环而不是 4 个 for 循环