我的一个方法中有以下代码:
foreach (var s in vars)
{
foreach (var type in statusList)
{
if (type.Id == s)
{
Add(new NameValuePair(type.Id, type.Text));
break;
}
}
}
这对我来说似乎有些无效,我想知道是否有办法用LINQ查询替换至少一个foreach。有什么建议吗?
编辑: vars是一个字符串数组,Add方法将一个项添加到CSLA NameValueList。
答案 0 :(得分:12)
基本上:
var types =
from s in vars
let type = (
from tp in statusList
where tp.Id == s ).FirstOrDefault()
where type != null
select new NameValuePair(type.Id, type.Text)
答案 1 :(得分:6)
编辑:我之前没有注意到break;
如果可能有多个具有相关ID的类型,则您需要使用FirstOrDefault
按Keith's answer或我的第二个代码示例。
编辑:删除“multi-from”版本,因为假设相等/哈希码适用于type.Id
的任何类型,它会产生不必要的低效率。
连接可能更合适:
var query = from s in vars
join type in statusList on s equals type.Id
select new NameValuePair(type.Id, type.Text);
foreach (var pair in query)
{
Add(pair);
}
您可能希望制作一个AddRange
方法,该方法需要IEnumerable<NameValuePair>
,您可以拨打AddRange(query)
。
或者,您可以使用LookUp。此版本确保每个“s”只添加一种类型。
var lookup = types.ToLookup(type => type.Id);
foreach (var s in vars)
{
var types = lookup[s];
if (types != null)
{
var type = types.First(); // Guaranteed to be at least one entry
Add(new NameValuePair(type.Id, type.Text));
}
}
这样做的好处是,它基本上只会通过类型列表来构建一个字典。
答案 2 :(得分:2)
这样的事情:
foreach(var s in vars) {
var type = statusList.FirstOrDefault(t => t.Id == s);
if (type != null)
Add(new NameValuePair(type.Id, type.Text));
}
或者如果vars支持ForEach
方法,这也会有效(但我建议不要使用overLINQifying):
vars.ForEach(s => {
var type = statusList.FirstOrDefault(t => t.Id == s);
if (type != null)
Add(new NameValuePair(type.Id, type.Text));
});
我假设type
是引用类型的实例。
答案 3 :(得分:2)
如果您的Add方法正在构建列表,您也可以尝试:
IEnumarable<NamedValuePair> result = statusList.Where(type => type.Id == s).Select(new NameValuePair(type => type.Id, type.Text));
答案 4 :(得分:1)
Bart de Smet有一个针对IEnumerable的扩展ForEach的实现。
答案 5 :(得分:1)
我没有看到群组加入的答案,所以这里有一个:
var result = vars
.GroupJoin
(
statusList,
s => s,
type => type.Id,
(s, g) => g.Any() ? g.First() : null
)
.Where(type => type != null)
.Select(type => new NameValuePair(type.Id, type.Text));