如何省略选择lambda中的值
本文关键字:lambda 何省略 选择 | 更新日期: 2023-09-27 18:01:24
我想做一个简单的CSV解析器。它应该遍历一个逗号分隔的值列表,并将它们放在IList<int>
中。这些值应该是整数。如果一个值是不可解析的,我只想忽略它。
这是我到目前为止的代码:
csv.Split(',').Select(item =>
{
int parsed;
if (int.TryParse(item, out parsed))
{
return parsed;
}
continue; //is not allowed here
}).ToList();
然而,这里(当然)不允许使用continue
。如何省略一个值在我的选择实现?
注意:我当然可以使用foreach或LINQ表达式,但我想知道如何使用lambda。
如何:
public static IEnumerable<int> ExtractInt32(this IEnumerable<string> values) {
foreach(var s in values) {
int i;
if(int.TryParse(s, out i)) yield return i;
}
}
:
var vals = csv.Split(',').ExtractInt32().ToList();
这里的优点:
- 避免魔幻的"哨兵"数字(如
int.MinValue
) - 避免了一个单独的和断开连接的"it is valid"/"parse"步骤(所以没有重复)
Select
转换值。它不会过滤。Where
正在这样做:
csv.Split(',')
.Select(item =>
{
int parsed;
return new { IsNumber = int.TryParse(item, out parsed),
Value = parsed };
})
.Where(x => x.IsNumber)
.Select(x => x.Value);
另外,请参考下面这个聪明而简短的答案。请注意,这里"聪明"的意思并不完全是肯定的。
一种方法是返回一些默认值,然后跳过它。
errorInt = int.MinValue;
csv.Split(',').Select(item =>
{
int parsed;
if (int.TryParse(item, out parsed))
{
return parsed;
}
else
{
return errorInt;
}
}).Where(val => val != errorInt).ToList();
我认为你有三个选择:
- 请使用
SelectMany
,它将允许您以空可枚举对象返回您希望省略的元素(或者长度为1的可枚举对象)。 - 使用一个你确定不会在集合中出现的int值(例如
-1
)来表示"省略",然后将它们过滤掉。这种方法是脆弱的,因为您可能会选择一个随后出现在集合中的值,这将导致一个微妙的错误。(你可以通过使用更大的数据类型来缓解这个问题,例如long
并选择int
范围之外的值,但随后你将需要转换回int
。) - 使用
Nullable<int>
(int?
)代替,然后过滤掉null
的值。
1:
csv.Split(',').SelectMany(item =>
{
int parsed;
if (int.TryParse(item, out parsed))
{
return new[] {parsed};
}
return Enumerable.Empty<int>();
}
3:
csv.Split(',').Select(item =>
{
int parsed;
if (int.TryParse(item, out parsed))
{
return (int?) parsed;
}
return (int?) null;
}
.Where(item => item.HasValue)
.Select(item => item.Value);
try this:
int dummy;
sv.Split(',').Where(c => int.TryParse(c,out dummy)).Select(c => int.Parse(c));
int.TryParse(..)
只是检查它是否是一个要转换为int型的有效字符串。out参数被忽略——我们不再需要它。
我们知道,只有那些"符合"Select()
的字符串值才可以安全地解析为int值。
为什么不在数组上使用Where
,然后只选择合适的整数
csv.Split(',')
.Where(item =>
{
int parsed;
return int.TryParse(item, out parsed);
})
.Select(item => Convert.ToInt32(item));
我可能会直接使用:
csv.Split(',').Where(item => isValid(item)).Select(item => TransformationExpression(item));
或
csv.Split(',').Select(item => ReturnsDummyValueIfInvalid(item)).Where(item => item != DummyValue);
int TempInt;
List<int> StuffIWant = csv.Split(',').Where(item => int.TryParse(item, TempInt)).ToList();