在LINQ中过滤时建立外部列表 [英] Building an external list while filtering in LINQ

查看:45
本文介绍了在LINQ中过滤时建立外部列表的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个输入字符串数组,其中包含电子邮件地址或域名\帐户形式的帐户名.我想建立一个仅包含电子邮件地址的字符串列表.如果输入数组中的元素的格式为domain \ account,我将在字典中执行查找.如果在词典中找到了密钥,则该值为电子邮件地址.如果找不到,则不会将其添加到结果列表中.下面的代码将使上面的描述清楚:

I have an array of input strings that contains either email addresses or account names in the form of domain\account. I would like to build a List of string that contains only email addresses. If an element in the input array is of the form domain\account, I will perform a lookup in the dictionary. If the key is found in the dictionary, that value is the email address. If not found, that won't get added to the result list. The code below will makes the above description clear:

private bool where(string input, Dictionary<string, string> dict)
{
    if (input.Contains("@"))
    {                
        return true;
    }
    else
    {
       try
       {
           string value = dict[input];             
           return true;
       }
       catch (KeyNotFoundException)
       {
           return false;
       }
    }
}

private string select(string input, Dictionary<string, string> dict)
{
    if (input.Contains("@"))
    {                
        return input;
    }
    else
    {
        try
        {
            string value = dict[input];                    
            return value;
        }
        catch (KeyNotFoundException)
        {
            return null;
        }
    }
}
public void run()
{
    Dictionary<string, string> dict = new Dictionary<string, string>()
    {
        { "gmail\\nameless", "nameless@gmail.com"}
    };    

    string[] s = { "anonymous@gmail.com", "gmail\\nameless", "gmail\\unknown" };
    var q = s.Where(p => where(p, dict)).Select(p => select(p, dict));
    List<string> resultList = q.ToList<string>();
}

虽然上面的代码有效(希望我在这里没有任何错别字),但是上面有两个我不喜欢的问题:

While the above code works (hope I don't have any typo here), there are 2 problems that I do not like with the above:

  1. where()和select()中的代码似乎是重复的/重复的.
  2. 需要2次通过.第二遍将查询表达式转换为List.

所以我想直接在where()方法中添加到list resultList中.看来我应该能够做到.这是代码:

So I would like to add to the List resultList directly in the where() method. It seems like I should be able to do so. Here's the code:

private bool where(string input, Dictionary<string, string> dict, List<string> resultList)
{
    if (input.Contains("@"))
    {                
        resultList.Add(input);  //note the difference from above
        return true;
    }
    else
    {
       try
       {
           string value = dict[input];
           resultList.Add(value); //note the difference from above             
           return true;
       }
       catch (KeyNotFoundException)
       {
           return false;
       }
    }
}

我的LINQ表达式可以很容易地在1条语句中显示:

The my LINQ expression can be nicely in 1 single statement:

List<string> resultList = new List<string>();
s.Where(p => where(p, dict, resultList));

var q = s.Where(p => where(p, dict, resultList)); //do nothing with q afterward

这似乎是完美且合法的C#LINQ.结果是:有时它起作用,有时不起作用.那么,为什么我的代码不能可靠地工作,我又该如何做呢?

Which seems like perfect and legal C# LINQ. The result: sometime it works and sometime it doesn't. So why doesn't my code work reliably and how can I make it do so?

推荐答案

如果将where和select取反,则可以先将未知的域帐户转换为null,然后将其过滤掉.

If you reverse the where and the select you can convert unknown domain accounts to null first, then just filter them out.

private string select(string input, Dictionary<string, string> dict)
{
    if (input.Contains("@"))
    {                
        return input;
    }
    else
    {
        if (dict.ContainsKey(input))
            return dict[input];
    }
    return null;
}

var resultList = s
    .Select(p => select(p, dict))
    .Where(p => p != null)
    .ToList()

这将处理您的重复代码.

This takes care of your duplicate code.

需要2次通过.第二遍将查询表达式转换为List.

It takes 2 passes. The second pass converts from the query expression to List.

实际上,这只是一遍,因为LINQ被懒惰地评估了.这就是为什么您的最后一条语句有时仅起作用的原因.如果评估了LINQ查询,则仅应用过滤器并生成您的列表.否则,Where语句将永远不会运行.

Actually this is only one pass as LINQ is lazy evaluated. This is why your last statements only work sometimes. The filter is only applied and your list generated if the LINQ query is evaluated. Otherwise the Where statement is never run.

这篇关于在LINQ中过滤时建立外部列表的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆