user1781232
user1781232

Reputation: 669

Return Dictionary value if key substring exist

I want to return the value from a dictionary if the key contains a string which half matches string lookup.

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"},
}

Forexample,

I have a string "abc1.somename", I am building up the logic as below - which doesn't work at the moment - to get me the value given key name contains that substring. I expect to get "6x.3.xx.xx" back.

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

    return value.ToString();
}

Edit:

Sorry guys, forget to mention the string that is passed in to do a look up doesn't exactly match either. It has a .co.uk appended to it :(

So it will be abc1.somename.co.uk but the dictionary has ip.qwer3.abc1.somename without the .co.uk

Upvotes: 3

Views: 6508

Answers (5)

Igor Quirino
Igor Quirino

Reputation: 1195

Try this online https://dotnetfiddle.net/q6E1wR

This will cutting right dots - My answer:

Usage:

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

For single result:

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

For multiple results:

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

Dependency:

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

Happy to help you!

Upvotes: 4

George Vovos
George Vovos

Reputation: 7618

First search for an exact match and then for a partial match.then use a regular expression

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

More on regular expression here
https://www.google.ie/?gws_rd=cr,ssl&ei=4z1XVv-oMsGsPMagotAG#q=c%23+regular+expressions

Upvotes: 0

Tim Schmelter
Tim Schmelter

Reputation: 460058

public string LookUpPeerIp(string deviceName)
{
    var keySubstringMatch = _ipAddressesDictionary.Keys
        .FirstOrDefault(key => key.Contains(deviceName));
    if(keySubstringMatch == null)
        return null;
    else
        return _ipAddressesDictionary[keySubstringMatch];
} 

maybe multiple matches are possible, then this would be a good approach:

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

Then you can process all matches, for example:

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

Upvotes: 3

Ric
Ric

Reputation: 13248

This will do it:

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

Upvotes: 2

Fede
Fede

Reputation: 4016

If you want to return all the values (or the first value) for a key that contains part of a string, you have no other way other than iterate over all the keys and return the one that suits your needs. That would be O(N) in complexity.

If instead of a contains you can live with a begins with, then a dictionary is not a good choice. You will get better performance with a Trie. There is no built in implementation of a Trie in the framework, but there are a couple of open source implementations available out there.

Upvotes: 1

Related Questions