用LINQ查询替换foreach

时间:2009-02-26 09:09:04

标签: c# .net linq

我的一个方法中有以下代码:

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。

6 个答案:

答案 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的类型,则您需要使用FirstOrDefaultKeith'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));