2015-11-26 4 views
3

Я хочу вернуть значение из словаря, если ключ содержит строку, которая наполовину соответствует поиску строки.Возвращаемое значение словаря, если существует ключевая подстрока

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,

У меня есть строка «abc1.somename», я строю до логики, как показано ниже - , который не работает в данный момент - получить мне значение данное ключевое имя содержит эту подстроку. Я ожидаю получить «6x.3.xx.xx» назад.

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

    return value.ToString(); 
} 

Edit:

Извините ребята, забыл упомянуть строку, которая передается, чтобы сделать смотреть не точно соответствует либо. Он имеет .co.uk прилагаемую к нему :(

Так будет abc1.somename.co.uk но словарь имеет ip.qwer3.abc1.somename без .co.uk

+1

Что он должен вернуть, если в словаре есть несколько ключей, содержащих подстроку, например '' ip.qwer'' из вашего примера? –

+0

Что делать, если 2 ключа содержат ваше имя устройства? –

+0

@JamesThorpe Это никогда не будет иметь значение для строки поиска. – user1781232

ответ

3

Попробуйте это онлайн 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(); 
} 

Рад помочь вам!

+0

поиск строки точно не соответствует. Пожалуйста, ознакомьтесь с изменениями к моему первоначальному вопросу. Спасибо – user1781232

+0

У меня есть ответ! Смотрите сейчас! ;) –

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")); 
+0

Отличная идея, но я просто понял - добавить к сложности - поиск строк точно не соответствует. Пожалуйста, ознакомьтесь с изменениями к моему первоначальному вопросу. Спасибо – user1781232

+1

@ user1781232 ваше редактирование полностью изменило вопрос! вы должны сказать, что сказали это в первую очередь. вам лучше задать другой вопрос. но не забудьте указать какие-либо важные вещи, потому что решения могут измениться в отношении этих вещей. –

1

Если вы хотите вернуть все значения (или первое значение) для ключа, содержащего часть строки, у вас нет другого способа, кроме повторения всех ключей, и возврата тех, которые соответствуют вашим потребностям. Это будет O (N) по сложности.

Если вместо a содержит вы можете жить с начала, значит, словарь не является хорошим выбором. Вы получите лучшую производительность с помощью Trie. В структуре нет встроенной реализации Trie, но есть пара доступных версий с открытым исходным кодом.

0

Это будет делать это:

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

Я только что понял - добавить к сложности - поиск строк точно не соответствует. Пожалуйста, ознакомьтесь с изменениями к моему первоначальному вопросу. Спасибо – user1781232

0

Первый поиск точного совпадения, а затем для частичного match.then использовать регулярное выражение

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

+0

Отличная идея, но я просто понял - добавить к сложности - поиск строк точно не соответствует. Пожалуйста, ознакомьтесь с изменениями к моему первоначальному вопросу. Спасибо – user1781232

+0

Если у вас нет точного или частичного соответствия, вы можете использовать регулярные выражения –