是否可以对字典字符串键进行部分字符串匹配?

发布于 2024-12-10 16:26:17 字数 406 浏览 0 评论 0 原文

我的代码中有一个 Dictionary> ,我按以下方式使用它:

Key           Values  
2011-07-15    1, 2, 3
2011-07-20    4, 5, 6
2010-02-11    7, 8, 9

我的代码需要能够查询与键中特定子字符串匹配的所有值。例如,如果我有子字符串 2011-07 它应该返回值 {1, 2, 3, 4, 5, 6}11 的子字符串应返回 1-9 中的所有 ID。

谁能推荐一种简洁的方法来实现这一目标?或者提供更好的数据结构来检索这些信息?

I have a Dictionary<string, List<int>> in my code which I am using in the following manner:

Key           Values  
2011-07-15    1, 2, 3
2011-07-20    4, 5, 6
2010-02-11    7, 8, 9

My code needs to be able to query for all values matching a particular substring in the key. For example, if I had the substring 2011-07 it should return values {1, 2, 3, 4, 5, 6}. A substring of 11 should return all IDs from 1-9.

Can anyone recommend a concise way to achieve this? Or provide a better data structure for retrieving this information?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

清醇 2024-12-17 16:26:17

我会做一个扩展方法:

public static class DictionaryExt
{
    public static IEnumerable<T> PartialMatch<T>(this Dictionary<string, T> dictionary, string partialKey)
    {
        // This, or use a RegEx or whatever.
        IEnumerable<string> fullMatchingKeys = 
            dictionary.Keys.Where(currentKey => currentKey.Contains(partialKey));

        List<T> returnedValues = new List<T>();

        foreach (string currentKey in fullMatchingKeys)
        {
            returnedValues.Add(dictionary[currentKey]);
        }

        return returnedValues;
    }
}

向字典添加值的“成本”不会改变,但检索的成本会更高,但前提是您知道要进行部分匹配。

顺便说一句,我确信您可以将其转换为单个 Lambda 表达式,但概念保持不变。

编辑:在您的示例中,此方法将返回 2 个值列表,但您可以更改它以合并列表。这是您可以执行的扩展方法:

public static IEnumerable<T> PartialMatch<T>(
    this Dictionary<string, IEnumerable<T>> dictionary,
    string partialKey)
{
    // This, or use a RegEx or whatever.
    IEnumerable<string> fullMatchingKeys = 
        dictionary.Keys.Where(currentKey => currentKey.Contains(partialKey));

    List<T> returnedValues = new List<T>();

    foreach (string currentKey in fullMatchingKeys)
    {
        returnedValues.AddRange(dictionary[currentKey]);
    }

    return returnedValues;
}

编辑 2:想想看,您还可以使其更通用。使用下一个扩展方法,它可以在任何字典上工作,只要您提供一个比较器来检查“部分匹配”的含义:

public static IEnumerable<TValue> PartialMatch<TKey, TValue>(
    this Dictionary<TKey, IEnumerable<TValue>> dictionary,
    TKey partialKey,
    Func<TKey, TKey, bool> comparer)
{
    // This, or use a RegEx or whatever.
    IEnumerable<TKey> fullMatchingKeys = 
        dictionary.Keys.Where(currentKey => comparer(partialKey, currentKey));

    List<TValue> returnedValues = new List<TValue>();

    foreach (TKey currentKey in fullMatchingKeys)
    {
        returnedValues.AddRange(dictionary[currentKey]);
    }

    return returnedValues;
}

I would do an extension method :

public static class DictionaryExt
{
    public static IEnumerable<T> PartialMatch<T>(this Dictionary<string, T> dictionary, string partialKey)
    {
        // This, or use a RegEx or whatever.
        IEnumerable<string> fullMatchingKeys = 
            dictionary.Keys.Where(currentKey => currentKey.Contains(partialKey));

        List<T> returnedValues = new List<T>();

        foreach (string currentKey in fullMatchingKeys)
        {
            returnedValues.Add(dictionary[currentKey]);
        }

        return returnedValues;
    }
}

The "cost" of adding values to the dictionary wouldn't change, but the cost of retrieval would be higher, but only when you know you're going with a partial match.

Btw, I'm sure you could transform this in a single Lambda expression, but the concept remains the same.

Edit: In your example, this method would return 2 lists of values, but you can change it to merge the lists. Here is the extension method you could do :

public static IEnumerable<T> PartialMatch<T>(
    this Dictionary<string, IEnumerable<T>> dictionary,
    string partialKey)
{
    // This, or use a RegEx or whatever.
    IEnumerable<string> fullMatchingKeys = 
        dictionary.Keys.Where(currentKey => currentKey.Contains(partialKey));

    List<T> returnedValues = new List<T>();

    foreach (string currentKey in fullMatchingKeys)
    {
        returnedValues.AddRange(dictionary[currentKey]);
    }

    return returnedValues;
}

Edit 2: Come to think of it, you could also make it more generic. With the next extension method, it would work on any dictionary, as long as you provide a comparer that check what you mean by "partial match" :

public static IEnumerable<TValue> PartialMatch<TKey, TValue>(
    this Dictionary<TKey, IEnumerable<TValue>> dictionary,
    TKey partialKey,
    Func<TKey, TKey, bool> comparer)
{
    // This, or use a RegEx or whatever.
    IEnumerable<TKey> fullMatchingKeys = 
        dictionary.Keys.Where(currentKey => comparer(partialKey, currentKey));

    List<TValue> returnedValues = new List<TValue>();

    foreach (TKey currentKey in fullMatchingKeys)
    {
        returnedValues.AddRange(dictionary[currentKey]);
    }

    return returnedValues;
}
只怪假的太真实 2024-12-17 16:26:17

您正在寻找简洁的答案。如果没有低级别的文本索引(我不知道任何专门的 .Net 类),我认为字典仍然是您最好的选择。使用如下内容进行查询:

myDictionary.Where(kvp => kvp.Key.Contains("11")).SelectMany(kvp => kvp.Value);

您必须搜索所有键无论如何,对于通用子字符串,没有一些非常酷的魔法(.Net 未提供),因此 LINQ 在这里不会对您造成太大伤害。

You are looking for concise answers. Without fancy indexing at a low-level for text (of which I don't know of any specialized .Net classes), I think dictionary is still your best bet. Query with something like:

myDictionary.Where(kvp => kvp.Key.Contains("11")).SelectMany(kvp => kvp.Value);

You have to search through all keys for a generalized substring anyway without some pretty cool magic (not provided by .Net), so LINQ shouldn't hurt you much here.

魄砕の薆 2024-12-17 16:26:17

如果 Dictionary 使用内部哈希值,那么你就不走运了,因为相似的字符串会产生不同的哈希值。我刚刚在周末用 C 语言实现了这个要求的解决方案,面试测试/作业。我使用排序数组作为底层结构 - 昂贵的插入,但快速查找(使用二分搜索)。要查找键以前缀开头的所有条目,我会找到第一个,然后继续下一个,下一个...对于一般子字符串,即不仅仅是前缀,我的解决方案将不起作用。目前我不知道对“常规子字符串”搜索有何建议。

If Dictionary uses internally hashes, you are out of luck, as similar strings yield dissimilar hashes. I just implemented solution to this requirement over the weekend in C, an interview test/homework. I used a sorted array as the underlying structure - expensive inserts, but fast lookups (using binary search). To find all entries with key starting with a prefix, I would find the 1st, then just go next, next... For general substring, i.e. not only prefix, my solution would not work. At this moment I do not know what to suggest for the "general substring" search.

残月升风 2024-12-17 16:26:17

你可以拥有三本字典。年、月、日。

请注意,当您将项目添加到三个词典时,您并不是在复制这些项目。

当您使用两个键拉出项目时,可以使用 LINQ 扩展方法 Intersect() 来获取与两个键匹配的项目(在两个结果集上使用 Intersect)。

警告,这样做不会导致执行速度最快的代码。

You could have three dictionaries. Year, Month, Day.

Note that when you add items to three dictionaries, you are NOT duplicating the items.

When you pull items out using two keys, you could use the LINQ Extension method Intersect() to get the items that match both keys (Use Intersect on the two result sets).

Caveat, doing it this way would not result in the fastest executing code.

岛歌少女 2024-12-17 16:26:17

一种简洁的方法是使用多值映射。

例如:

Dictionary<string, Dictionary<string, List<int>>

为什么不将 2011-07 存储为键,将 15 存储为内部字典键,将 1,2,3 存储为值。

地图["2011-07"]["15"]= {1,2,3};

如果您只想要 2011-07 您可以通过遍历获取其他字典中的所有内容。

map["2011-07"] // 将返回 u 1,2,3,4,5,6

,如果您想要前往特定日期,2011-07-15 这将仅返回 1,2,3

foreach(var element in map["2011-07"]){

     var values = element.values; // and you can append them to a list.

}

,如果您需要年/月/日, ,您将需要多级字典。或者您也可以使用

A concise way would be to use Multivalue Map.

For example:

Dictionary<string, Dictionary<string, List<int>>

why dont you store the 2011-07 as a key and 15 for the inner dictionary key and 1,2,3 as values.

map["2011-07"]["15"]= {1,2,3};

if you want just 2011-07 you can get everything within the other dictionary by traversal.

map["2011-07"] // would return u 1,2,3,4,5,6

and if you want to go to a specific day, 2011-07-15, this would return u only 1,2,3

foreach(var element in map["2011-07"]){

     var values = element.values; // and you can append them to a list.

}

if you will need year/month/day, you will need multilevel dictionaries. or you can use a Tree as well.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文