Linq替代按键(或部分键)

时间:2015-10-26 16:27:20

标签: c# linq

我正在处理以下代码,以根据用户将指定的搜索短语查找“说明”。将Keys视为重要的短语,将值视为关于在哪里找到该短语的描述 可以把它想象成一个商店定位器(我能想到最好的比喻)。如果您搜索“目标”(键),您将获得大量的城市(价值),有些可能具有相同的名称。因此,同一城市可以有多个目标 Dictionary显然不起作用,因为我要么有重复的商店名称,要么可能有重复的城市名称。这让我了解了我的实际情况:

基本上,我从一个List<KeyValuePair<string, string>>开始,允许在两个方向上重复,然后将其转换为Lookup<string, string>,我认为这将比现在更难以混淆。

List<KeyValuePair<string, string>> kvpList = new List<KeyValuePair<string, string>>();
Lookup<string, string> collection;

kvpList.Add(new KeyValuePair<string, string>("K1", "R1"));
kvpList.Add(new KeyValuePair<string, string>("K1", "R1"));
kvpList.Add(new KeyValuePair<string, string>("K1", "R2"));
kvpList.Add(new KeyValuePair<string, string>("K2", "R1"));
kvpList.Add(new KeyValuePair<string, string>("K2", "R2"));
kvpList.Add(new KeyValuePair<string, string>("K2", "R3"));
kvpList.Add(new KeyValuePair<string, string>("K2", "R1"));

collection = (Lookup<string,string>)kvpList.ToLookup(k => k.Key, k => k.Value);

以上只是虚假的测试信息,但我觉得必须有一种更清晰的方法来获取Lookup的结果,特别是因为它看起来非常符合Linq。不幸的是,我对Linq很不熟悉,Linq本身的语法似乎并不适合初学者友好。我在此代码中得到了结果(硬编码搜索术语仅用于测试目的):

string searchTerm = "K2";
List<string> uniqueResults = new List<string>();

foreach (var item in collection)
{
    if (item.Key.Contains(searchTerm))
    {
        foreach (var value in item)
        {
            if (!uniqueResults.Contains(value))
            {
                uniqueResults.Add(value);
                Console.WriteLine("Added: " + value);
            }
            else
            {
                Console.WriteLine("Skipped duplicate: " + value);
            }
        }
    }
}  

我没有上述代码的问题,但我的问题是:有没有办法使用Linq来实现我想要实现的目标?我觉得我所拥有的并不是最好的办法...... 值得注意的是,部分searchTerm 还必须能够在密钥中找到结果(因此包含)。现有答案无法回答我的具体问题。我无法通过部分密钥搜索找到一个帮助我获取值。

2 个答案:

答案 0 :(得分:6)

您转换为LINQ的代码如下所示:

var uniqueResults = collection
        .Where(item => item.Key.Contains(searchTerm)) // filter the collection
        .SelectMany(x => x)                           // flatten results
        .Distinct()                                   // remove duplicates
        .ToList();

您甚至不需要Lookup。您可以使用kvpList获得相同的结果:

var uniqueResults = kvpList
        .Where(item => item.Key.Contains(searchTerm)) // filter the collection
        .Select(item => item.Value)                   // get the Values from KeyValuePairs
        .Distinct()                                   // remove duplicates
        .ToList();

LINQ解决方案实际上比命令式解决方案更容易理解。尝试用英语描述您的算法:从kvpList,选择其中包含搜索词的不同值。这几乎就是第二个LINQ代码。

答案 1 :(得分:1)

您可以使用LINQ和HashSet<string>,这样可以消除重复:

var uniqueResults = collection.Where(item => item.Contains(searchTerm))
                              .SelectMany(x => x)
                              .ToHashSet();

ToHashSet是自定义扩展方法,您可以轻松创建:

public static class EnumerableExtensions
{
    public static HashSet<T> ToHashSet(this IEnumerable<T> enumerable)
    {
        return new HashSet<T>(enumerable);
    }
}