簡體   English   中英

C#Linq / Lambda表達式:如何從字符串中選擇一個整數?

[英]C# Linq/Lambda expression: How to select an integer out of a string?

我認為解釋我的問題的最好方法是使用簡短的(通用的)linq-to-objects代碼示例:

IEnumerable<string> ReadLines(string filename)
{
    string line;
    using (var rdr = new StreamReader(filename))
        while ( (line = rdr.ReadLine()) != null)
           yield return line;
}

IEnumerable<int> XValuesFromFile(string filename)
{
    return ReadLines(filename)
               .Select(l => l.Substring(3,3))
               .Where(l => int.TryParse(l))
               .Select(i => int.Parse(i));
}

請注意,此代碼解析整數兩次。 我知道我錯過了一種明顯的簡單方法來安全地消除其中一個呼叫(因為我之前已經完成了)。 我現在找不到它。 我怎樣才能做到這一點?

怎么樣:

int? TryParse(string s)
{
    int i;
    return int.TryParse(s, out i) ? (int?)i : (int?)null;
}
IEnumerable<int> XValuesFromFile(string filename)
{
    return from line in ReadLines(filename)
           let start = line.Substring(3,3)
           let parsed = TryParse(start)
           where parsed != null
           select parsed.GetValueOrDefault();
}

如果你願意,你可以組合第二/第三行:

    return from line in ReadLines(filename)
           let parsed = TryParse(line.Substring(3,3))

GetValueOrDefault的選擇是因為它跳過了cast (int).Value執行的驗證檢查 - 即它(稍微有點)更快(我們已經檢查過它不是null )。

這不是很漂亮,但你可以這樣做:

return ReadLines(filename)
    .Select(l =>
                {
                    string tmp = l.Substring(3, 3);
                    int result;
                    bool success = int.TryParse(tmp, out result);
                    return new
                               {
                                   Success = success,
                                   Value = result
                               };
                })
    .Where(i => i.Success)
    .Select(i => i.Value);

當然,這主要是將工作推入lambda,但它確實提供了正確的答案,只需一次解析(但額外的內存分配)。

我想我會用這樣的東西:

IEnumerable<O> Reduce<I,O>(this IEnumerable<I> source, Func<I,Tuple<bool, O>> transform )
{
    foreach (var item in source)
    {
       try
       {
          Result<O> r = transform(item);
          if (r.success) yield return r.value;
       }
       catch {}
    }
}

ReadLines().Reduce(l => { var i; new Tuple<bool, int>(int.TryParse(l.Substring(3,3),i), i)} );

不過,我真的不喜歡這個,因為我已經在記錄中,因為不喜歡用這種方式使用元組 不幸的是,除了濫用異常或將其限制為引用類型(其中null被定義為失敗的轉換)之外,我沒有看到許多替代方案,這兩種情況都不是更好。

暫無
暫無

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

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