[英]C#: How to manipulate List<String> using LINQ or LAMBDA expression
[英]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.