【问题标题】:Return Dictionary value if key substring exist如果键子字符串存在,则返回字典值
【发布时间】:2016-02-29 19:58:11
【问题描述】:

如果键包含与字符串查找匹配一半的字符串,我想从字典中返回值。

private readonly Dictionary<string, string> _ipAddressesDictionary = new Dictionary<string, string>()
{
       {"ip.qwer4.abc5.somename", "6x.x.00.xx"},
       {"ip.qwer3.abc1.somename", "6x.3.xx.xx"},
}

例如,

我有一个字符串“abc1.somename”,我正在构建如下逻辑 - 目前不起作用 - 为我获取 给定的键名包含该子字符串。我希望得到“6x.3.xx.xx”。

public string LookUpPeerIp(string deviceName)
{
    var value = _ipAddressesDictionary.Keys.Contains(deviceName);

    return value.ToString();
}

编辑:

对不起,伙计们,忘记提及传入进行查找的字符串也不完全匹配。它附加了一个 .co.uk :(

所以它将是 abc1.somename.co.uk 但字典有 ip.qwer3.abc1.somename 没有 .co.uk

【问题讨论】:

  • 如果包含子字符串的字典中有多个键,例如您的示例中的"ip.qwer",它应该返回什么?
  • 如果 2 个键包含您的 deviceName 怎么办?
  • @JamesThorpe 对于查找字符串而言,情况永远不会如此。
  • @GeorgeVovos 希望不会是这样,如果是这样,请返回 First()
  • 好的 - 但我喜欢你在 1 条评论中从 "won't ever""hopefully wont" 的方式:) 谁知道未来会怎样......!

标签: c# list dictionary substring


【解决方案1】:

在线尝试https://dotnetfiddle.net/q6E1wR

这将切割正确的点 - 我的回答:

用法:

Console.WriteLine("--first");
Console.WriteLine(LookupByPrefix("abc1.somename.co.uk"));
Console.WriteLine("--many");
string[] many = LookupByPrefixMany("abc1.somename.co.uk");
foreach(string ip in many)
    Console.WriteLine(ip);

对于单个结果:

public string LookupByPrefix(string domainName)
{
    string[] dotDomains = domainName.Split('.');

    for(int matchCount = dotDomains.Length; matchCount > 0; matchCount--)
    {
        string[] ret = LookUpPeerIpMany(string.Join(".", dotDomains.Take(matchCount)));
        if(ret != null && ret.Length > 0) return ret.SingleOrDefault();
    }

    return null;
}

对于多个结果:

public string[] LookupByPrefixMany(string domainName)
{
    string[] dotDomains = domainName.Split('.');

    for(int matchCount = dotDomains.Length; matchCount > 0; matchCount--)
    {
        string[] ret = LookUpPeerIpMany(string.Join(".", dotDomains.Take(matchCount)));
        if(ret != null && ret.Length > 0) return ret;
    }

    return null;
}

依赖:

public string[] LookUpPeerIpMany(string deviceName)
{
    return _ipAddressesDictionary
           .Where(q=>q.Key.Contains(deviceName)).Select(q=>q.Value).ToArray();
}

很高兴为您提供帮助!

【讨论】:

  • 字符串查找不完全匹配。请查看对我原来问题的修改。谢谢
  • 我有答案!现在看! ;)
【解决方案2】:

首先搜索完全匹配,然后搜索部分匹配。然后使用正则表达式

public string LookUpPeerIp(string deviceName)
{
        string value = null;
        _ipAddressesDictionary.TryGetValue(deviceName, out value);
        if (value != null)
            return value;

        var keyPair = _ipAddressesDictionary.FirstOrDefault(k => k.Key.Contains(value));

        if (keyPair != null)
            return keyPair.Value;

        string pattern = @"your pattern";
        Regex rgx = new Regex(pattern, RegexOptions.IgnoreCase);

        keyPair = _ipAddressesDictionary.FirstOrDefault(k => rgx.IsMatch(k.Key));
        return keyPair != null ? keyPair.Value : null;
  }

这里有更多关于正则表达式的信息
https://www.google.ie/?gws_rd=cr,ssl&ei=4z1XVv-oMsGsPMagotAG#q=c%23+regular+expressions

【讨论】:

  • 好主意,但我刚刚意识到 - 增加复杂性 - 字符串查找不完全匹配。请查看对我原来问题的修改。谢谢
  • 如果您没有完全匹配或部分匹配,您可以使用正则表达式
【解决方案3】:
public string LookUpPeerIp(string deviceName)
{
    var keySubstringMatch = _ipAddressesDictionary.Keys
        .FirstOrDefault(key => key.Contains(deviceName));
    if(keySubstringMatch == null)
        return null;
    else
        return _ipAddressesDictionary[keySubstringMatch];
} 

也许多个匹配是可能的,那么这将是一个好方法:

public IEnumerable<string> LookUpPeerIp(string deviceName)
{
    var keySubstringMatch = _ipAddressesDictionary.Keys
        .Where(key => key.Contains(deviceName));
    foreach (string key in keySubstringMatch)
        yield return _ipAddressesDictionary[key];
} 

然后就可以处理所有的匹配了,例如:

string allMatching = String.Join(",", LookUpPeerIp("abc1.somename"));

【讨论】:

  • 好主意,但我刚刚意识到 - 增加复杂性 - 字符串查找不完全匹配。请查看对我原来问题的修改。谢谢
  • @user1781232 您的编辑完全改变了问题!你应该先说的。你最好再问一个问题。但请记住说明任何重要的事情,因为解决方案可能会根据这些事情发生变化。
【解决方案4】:

这样就可以了:

string partial = "abc5";
string value= _ipAddressesDictionary.FirstOrDefault(x => x.Key.Contains(partial)).Value;

【讨论】:

  • 我刚刚意识到 - 为了增加复杂性 - 字符串查找不完全匹配。请查看对我原来问题的修改。谢谢
【解决方案5】:

如果您想返回包含部分字符串的键的所有值(或第一个值),除了遍历所有键并返回适合您需要的键之外别无他法。这将是 O(N) 的复杂度。

如果您可以使用开头来代替包含,那么字典不是一个好的选择。使用Trie,您将获得更好的性能。框架中没有内置的 Trie 实现,但有几个可用的开源实现。

【讨论】:

    猜你喜欢
    • 2020-04-02
    • 1970-01-01
    • 2021-06-28
    • 1970-01-01
    • 2011-02-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-05-11
    相关资源
    最近更新 更多