Linq返回下一行有值的当前行

我需要处理作为单个 Excel 字符串列提供给我的发票,我已将其转换为List<string>. 一个简化的示例如下所示。


This is a nothing line

No001 FOO67 368.80

No001 FOO67 17.68

SHORT 12345

在此示例中,我可能需要从以“No”开头的每一行中提取数据——参考(例如 FOO67)和数量(例如 368.80)。但是,如果我遇到以“SHORT”开头的行,这意味着之前的行金额确实是一个调整,并且参考应该是我在“SHORT”行上找到的任何内容,并且金额的符号相反。在上述情况下,我希望提取的数据如下(第一行是列标题):


Reference    Amount

  FOO67      368.80

  12345      -17.68

我找不到使用针对列表的 linq 查询来实现此目的的任何方法。我认为解决方案可能看起来像这样的模型(下面不会解析,因为我添加了“nextline”作为伪代码添加):


var inv = new List<string> { "This is a nothing line", "No001 FOO67 368.80", "No001 FOO67 17.68", "SHORT 123456" };


var myTable = new DataTable();


myTable.Columns.Add("Id", typeof(int));

myTable.Columns.Add("Ref", typeof(string));

myTable.Columns.Add("Amount", typeof(double));


var foo = from l in inv

            where (l.Substring(0, 2) == "No" && double.TryParse(l.Split(' ')[2], out i))

            select myTable.LoadDataRow(new object[]

                    { inv.IndexOf(l)

                     ,nextline.Contains("SHORT")? nextline.Split(' ')[1] : l.Split(' ')[1]

                     ,nextline.Contains("SHORT")? -1:1 * double.Parse(l.Split(' ')[2].Replace(",", "").Replace("-", ""))

                    }, LoadOption.OverwriteChanges);

有没有一种已知的方法可以从查询的下一行获取值并使用它来决定要返回哪些行?如果是这样,这样做的方法是什么?


宝慕林4294392
浏览 113回答 2
2回答

守着星空守着你

您可以使用以下内容。var inv = new List<string>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;"This is a nothing line",&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;"No001 FOO67 368.80",&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;"No001 FOO67 17.68",&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;"SHORT 123456"&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; };var filterValidLines = inv.ToLookup(c=>c.StartsWith("No")&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ||c.StartsWith("SHORT"));var result = filterValidLines[true].Zip(&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; filterValidLines[true].Skip(1),&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; (x,y)=>{&nbsp;&nbsp; &nbsp; var subData= x.Split(new []{" "},StringSplitOptions.RemoveEmptyEntries);&nbsp; &nbsp; var multiplier = y.StartsWith("SHORT")? -1:1;&nbsp; &nbsp; return new Data{Reference= subData[1], Amount = double.Parse(subData[2]) * multiplier};});输出Reference AmountFOO67&nbsp; &nbsp; &nbsp;368.8&nbsp;FOO67&nbsp; &nbsp; &nbsp;-17.68&nbsp;

ITMISS

一个快速而肮脏的解决方案:void Main(){&nbsp; &nbsp; var list = new List<string>&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; "This is a nothing line",&nbsp; &nbsp; &nbsp; &nbsp; "No001 FOO67 368.80",&nbsp; &nbsp; &nbsp; &nbsp; "No001 FOO67 17.68",&nbsp; &nbsp; &nbsp; &nbsp; "SHORT 12345"&nbsp; &nbsp; };&nbsp; &nbsp; var invoices = list&nbsp; &nbsp; &nbsp; &nbsp; .Select((l, i) => new InvoiceData&nbsp; &nbsp; &nbsp; &nbsp; {&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Line = l,&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; NextLine = i < list.Count - 1 ? list[i + 1] : string.Empty&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; })&nbsp; &nbsp; &nbsp; &nbsp; .Where(x => x.Line.StartsWith("No"))&nbsp; &nbsp; &nbsp; &nbsp; .ToList();}public class InvoiceData{&nbsp; &nbsp; public string Line { get; set; }&nbsp; &nbsp; public string NextLine { get; set; }&nbsp; &nbsp; public bool IsAdjustment => NextLine.StartsWith("SHORT");&nbsp; &nbsp; public decimal Amount =>&nbsp; &nbsp; &nbsp; &nbsp; IsAdjustment&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ? -decimal.Parse(Line.Split(' ')[2])&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; : decimal.Parse(Line.Split(' ')[2]);&nbsp; &nbsp; public string Reference =>&nbsp; &nbsp; &nbsp; &nbsp; IsAdjustment&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ? NextLine.Split(' ')[1]&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; : Line.Split(' ')[1];}
打开App,查看更多内容
随时随地看视频慕课网APP