C# 用 LINQ 查询替换 foreach
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/589737/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Replacing foreach with LINQ query
提问by Sakkle
I have the following code in one of my methods:
我的方法之一中有以下代码:
foreach (var s in vars)
{
foreach (var type in statusList)
{
if (type.Id == s)
{
Add(new NameValuePair(type.Id, type.Text));
break;
}
}
}
This seems sort of ineffective to me, and I was wondering if there was a way to substitute at least one of the foreaches wih a LINQ query. Any suggestions?
这对我来说似乎有点无效,我想知道是否有办法用 LINQ 查询替换至少一个 foreaches。有什么建议?
EDIT:vars is an array of strings and the Add method adds an item to a CSLA NameValueList.
编辑:vars 是一个字符串数组,Add 方法将一个项目添加到 CSLA NameValueList。
采纳答案by Jon Skeet
EDIT: I hadn't noticed the break;before
编辑:我没有受人注目的break;前
If there could be more than one type with the relevant ID, then you need to use FirstOrDefaultas per Keith's answeror my second code sample below.
如果具有相关 ID 的类型可能不止一种,那么您需要FirstOrDefault按照Keith 的回答或我下面的第二个代码示例使用。
EDIT: Removing "multi-from" version as it's unnecessarily inefficient assuming equality/hashcode works for whatever the type of type.Idis.
编辑:删除“multi-from”版本,因为假设相等/哈希码适用于任何类型的type.Id情况,它的效率不必要地低下。
A join is probably more appropriate though:
不过,加入可能更合适:
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);
}
You might want to make an AddRangemethod which takes an IEnumerable<NameValuePair>at which point you could just call AddRange(query).
您可能想要创建一个AddRange方法,该方法IEnumerable<NameValuePair>在此时您可以调用AddRange(query).
Alternatively, you can use a LookUp. This version makes sure it only adds one type per "s".
或者,您可以使用 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));
}
}
The benefit of this is that it only goes through the list of types once to build up a dictionary, basically.
这样做的好处是它基本上只通过一次类型列表来构建字典。
回答by Mehrdad Afshari
Something like this:
像这样的东西:
foreach(var s in vars) {
var type = statusList.FirstOrDefault(t => t.Id == s);
if (type != null)
Add(new NameValuePair(type.Id, type.Text));
}
Or if vars supports ForEachmethod, this would work too (however I recommend against overLINQifying):
或者,如果 vars 支持ForEach方法,这也可以(但是我建议不要过度使用LINQifying):
vars.ForEach(s => {
var type = statusList.FirstOrDefault(t => t.Id == s);
if (type != null)
Add(new NameValuePair(type.Id, type.Text));
});
I assumed typeis an instance of a reference type.
我假设type是引用类型的实例。
回答by Keith
Basically:
基本上:
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)
回答by Jakob Christensen
Bart de Smethas an implementation of an extension ForEach for IEnumerable.
Bart de Smet为 IEnumerable 实现了 ForEach 扩展。
回答by Arcturus
If your Add method is constructing a list, you might also try:
如果您的 Add 方法正在构建一个列表,您也可以尝试:
IEnumarable<NamedValuePair> result = statusList.Where(type => type.Id == s).Select(new NameValuePair(type => type.Id, type.Text));
回答by Amy B
I don't see an answer with a group join, so here's one:
我没有看到加入群组的答案,所以这是一个:
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));

