簡體   English   中英

Linq返回當前行,其中下一行具有值

[英]Linq return current rows where the next row has value

我需要處理作為字符串的單個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);

有沒有一種已知方法可以從查詢的下一行獲取值並使用它來確定要返回的行? 如果是這樣,該怎么做?

您可以使用類似以下的內容。

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

var filterValidLines = inv.ToLookup(c=>c.StartsWith("No") 
                                              ||c.StartsWith("SHORT"));
var result = filterValidLines[true].Zip(
                            filterValidLines[true].Skip(1),
                            (x,y)=>
{ 
    var subData= x.Split(new []{" "},StringSplitOptions.RemoveEmptyEntries);
    var multiplier = y.StartsWith("SHORT")? -1:1;
    return new Data{Reference= subData[1], Amount = double.Parse(subData[2]) * multiplier};
});

輸出量

Reference Amount
FOO67     368.8 
FOO67     -17.68 

快速而骯臟的解決方案:

void Main()
{
    var list = new List<string>
    {
        "This is a nothing line",
        "No001 FOO67 368.80",
        "No001 FOO67 17.68",
        "SHORT 12345"
    };


    var invoices = list
        .Select((l, i) => new InvoiceData
        { 
            Line = l, 
            NextLine = i < list.Count - 1 ? list[i + 1] : string.Empty 
        })
        .Where(x => x.Line.StartsWith("No"))
        .ToList();
}

public class InvoiceData
{
    public string Line { get; set; }
    public string NextLine { get; set; }
    public bool IsAdjustment => NextLine.StartsWith("SHORT");
    public decimal Amount =>
        IsAdjustment 
            ? -decimal.Parse(Line.Split(' ')[2])
            : decimal.Parse(Line.Split(' ')[2]);
    public string Reference =>
        IsAdjustment
            ? NextLine.Split(' ')[1]
            : Line.Split(' ')[1];
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM