LINQ查询以修改列表
本文关键字:列表 修改 查询 LINQ | 更新日期: 2023-09-27 18:27:28
这似乎是一个难以破解的难题。我希望这对你们这些大师来说很容易。我想知道使用LINQ是否可以做到这一点。
这是我的清单:
ABC,1,RON,26,73
CDE,13,JON,21,18
ERROR,ERROR LINE,ERROR LINE,DEF
DEF,NOT AVAILABLE,"",JANE,32,13
GHI,23,DAWN,14,25
我需要用这个列表完成两件事:
- 将带有ERROR的行和下一行移动到列表底部
- ERROR之后的下一行(以"DEF"开头的行)必须进行修改,以便所有字段都与正确的字段对齐。但是,我仍然应该留在ERROR行之后
最后的列表应该是这样的:
ABC,1,RON,26,73
CDE,13,JON,21,18
GHI,23,DAWN,14,25
ERROR,ERROR LINE,ERROR LINE,DEF
DEF,NOT AVAILABLE,JANE,32,13
现在,我完整、详细的LINQ查询如下:
var myList = (File.ReadLines(myFile.ToString(), Encoding.GetEncoding(1250)))
.ToList()
.OrderBy(l => l[0].ToString())
.Select(l => new specialclass {
Comp = l[0].ToString(),
Place = Convert.ToInt32(l[1].ToString()),
Name = l[2].ToString(),
Limit = Convert.ToInt32(l[3].ToString()),
Limit2 = Convert.ToInt32(l[4].ToString())
});
这是另一种应该对您有所帮助的方法:
var data = System.IO.File.ReadAllLines(@"C:'Temp'Data.csv");
var result = new List<String>();
var errors = new List<Tuple<int, String, String>>();
for (int i = 0; i < data.Length; i++)
{
var line = data[i];
var cols = line.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
if (cols[0].ToUpper() == "ERROR")
{
var nextLine = data.Length > i+1 ? data[i + 1].Replace("'"'"","") : String.Empty;
var nextCols = nextLine.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries)
.Where(col => !String.IsNullOrWhiteSpace(col) && !(col.Trim() == "0"));
var errorInfo = Tuple.Create(i, line, String.Join(",", nextCols));
errors.Add(errorInfo);
i++;
}
else {
result.Add(line);
}
}
foreach(var error in errors)
{
result.Add(error.Item2);
result.Add(error.Item3);
}
尽管有其他警告,提供LINQ解决方案还是值得考虑的,即使它最终不是解决这个问题的正确方案。
我将提供一个LINQ解决方案,其中需要注意的是,一个适合生产的解决方案应该进行错误检查和参数验证,包括检查文件的格式是否正确,这很有趣,但超出了这里要求的范围,而且通常在功能上做起来有点困难。
var myList =
File.ReadLines(myFile.ToString(), Encoding.GetEncoding(1250))
.Select(line =>
{
var split = line.Split(',');
return new specialclass
{
Comp = split[0],
Place = Convert.ToInt32(split[1]),
Name = split[2],
Limit = Convert.ToInt32(split[3]),
Limit2 = Convert.ToInt32(split[4])
};
})
.ToList();
var itemsAndPrevious = new specialclass [] { null }
.Concat(myList)
.Zip(myList, (prev,item) => new { prev, item });
var itemsWithoutError =
itemsAndPrevious
.Where(i => i.item.Comp != "Error" // omit error line
&& (i.prev == null || i.prev.Comp != "Error")) // omit line following error lines
.Select(i => i.item)
.OrderBy(i => i.Comp);
var itemsWithError =
itemsAndPrevious.Where(i => i.prev != null && i.prev.Comp == "Error")
.OrderBy(i => i.item.Comp)
.SelectMany(i => new [] { i.prev, i.item });
var desiredResult = itemsWithoutError.Concat(itemsWithError);
如果您计划仅在包含几百甚至几千个条目的数据上运行此功能,则此功能可能表现良好,不需要找到更高效的解决方案。重要的是,你不要想当然地认为任何实现都足够快——只是为了确定时间。您还应该了解加倍的输入大小如何影响代码的运行时间,然后您就可以预测在越来越大的输入大小上这将如何执行。
我不保证以上代码经过测试或没有错误。Zip
是在4.0中添加的,因此如果您使用之前的框架,它将不可用。否则,实现自己的Zip
是一项有价值的工作。快乐的编码。