简体   繁体   English

Linq替代按键(或部分键)检索查找值

[英]Linq alternative to retrieving Lookup values by key (or partial key)

I am working on the following code to find a "description" based on a search phrase that the user will specify. 我正在使用以下代码来查找基于用户将指定的搜索短语的“描述”。 Think of the Keys as important phrases and the Values as a description on where to go to find that phrase. 将Keys视为重要的短语,将值视为关于在何处查找该短语的描述。
Think of it as a store locator for example (best analogy I can think up). 可以把它想象成一个商店定位器(我能想到最好的比喻)。 If you search "Target" (key), you'll get tons of cities (value) and some may have the same name. 如果您搜索“目标”(键),您将获得大量的城市(价值),有些可能具有相同的名称。 So there can be multiple Targets in the same city. 因此,同一城市可以有多个目标。
A Dictionary will obviously not work, because I'll either have duplicate store names, or possibly duplicate city names. Dictionary显然不起作用,因为我要么有重复的商店名称,要么可能有重复的城市名称。 Which brings me to my actual situation: 这让我了解了我的实际情况:

Basically, I'm starting from a List<KeyValuePair<string, string>> to allow for duplicates in both directions, then converting that to a Lookup<string, string> which I assumed would be less confusing than it is turning out to be. 基本上,我是从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);

The above is simply fake test information, but I feel like there must be a cleaner way to get the results from the Lookup especially since it appears to be very Linq-friendly. 以上只是虚假的测试信息,但我觉得必须有一种更清晰的方法来获取Lookup的结果,特别是因为它看起来非常符合Linq。 Unfortunately, I am quite unfamiliar with Linq, and the syntax of Linq itself doesn't seem to lend itself to be very beginner-friendly. 不幸的是,我对Linq很不熟悉,Linq本身的语法似乎并不适合初学者友好。 I get the results in this code (hard coded search term just for testing purposes): 我在此代码中得到了结果(硬编码搜索术语仅用于测试目的):

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);
            }
        }
    }
}  

I don't have issues with the above code, but my question is: Is there a way to use Linq to achieve what I am trying to accomplish? 我没有上述代码的问题 ,但我的问题是:有没有办法使用Linq来实现我想要实现的目标? I feel like what I have is not the best way this could be done... 我觉得我拥有的不是最好的办法......
It may be worth noting that a partial searchTerm must also be able to find results where it occurs in the key (hence contains). 值得注意的是,部分searchTerm 还必须能够找到密钥中出现的结果 (因此包含)。 Existing answers weren't quite able to answer my specific questions. 现有答案无法回答我的具体问题。 I was not able to find one to help me get values by a partial key search. 我无法通过部分密钥搜索找到一个帮助我获取值的人。

Your code translated to LINQ would look like this: 您转换为LINQ的代码如下所示:

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

You don't even need the Lookup . 你甚至不需要Lookup You can get the same results with kvpList : 您可以使用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();

The LINQ solution is actually much easier to understand than the imperative one. LINQ解决方案实际上比命令式解决方案更容易理解。 Try to describe your algorithm in English: From kvpList , select distinct values where key contains the search term. 尝试用英语描述您的算法:从kvpList ,选择其中key包含搜索词的不同值。 That's almost exactly the 2nd LINQ code. 这几乎就是第二个LINQ代码。

You could use LINQ and a HashSet<string> , which would eliminate duplicates for you: 您可以使用LINQ和HashSet<string> ,这将为您消除重复:

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

Where ToHashSet is a custom extension method you can create easily: ToHashSet是一种自定义扩展方法,您可以轻松创建:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM