2016-01-11 2 views
0

Итак, я пытаюсь найти персонажей в пределах X расстояния до каждого персонажа, с которым я перебираю. Таким образом, для примера ....Используя substr, чтобы найти близлежащих персонажей

nearby("abcdefg", 2) 

Если возвращать набор с каждым символом в качестве ключа и его значение закрытия на пределах расстояния 2. Он должен выглядеть так ...

dictionary('a' -> set(a, b, c), 'b' -> set(a, b, c, d), 'c' -> set(a,b,c,d,e)) 

Мой код прямо сейчас выглядит так ...

dictionary<char, set<char>> near(const std::string word, int dist) { 
    dictionary<char, set<char>> map; 
    for (int x = 0; x < word.size(); x++) { 
     for (char letter : word.substr(std::max(0, x - dist), std::min(dist + 1, int(word.size())))) 
      map[word[x]].insert(letter); 
    } 
    return map; 
} 

План выпуска: - Он работает по большей части, однако, из-за C++ 's су bstring Я не могу указать, что я хочу, чтобы все символы от индекса от 0 до 4. Вместо этого он индексируется в 0, а затем включает в себя что-либо в пределах диапазона 4. Это проблематично, когда я хочу вернуться назад, чтобы включить символы 4 буквы в передние и сзади.

На данный момент мой код будет правильным, но в конце оставить один символ. Таким образом, это выглядит так ...

nearby(abcdefg, 2) 
dictionary('c' -> set(a,b,c)) 

Это не соответствует d.

+0

Что это за классный словарь? Это просто 'std :: map'? Если да, напишите об этом. Кроме того, вы ссылаетесь на 'std :: min', но просто' set'. Это 'std: set'? Если нет, то что это? –

+0

Я полагаю, вы могли бы предположить это; они являются обычными классами, которые я создал, но я думал, что это не относится к самой проблеме. Просто знайте, что они работают так, как работают словари и наборы. Они отлично работают; проблема заключается в сращивании строки. –

ответ

1

Вам просто нужно:

 const auto start = std::max(0, x-dist); 
     const auto end = std::min(x+dist+1, int(word.size()); 
     const auto len = end - start; 
     const auto substring = word.substr(start,len); 
     auto &the_set = map[word[x]]; 
     for (const auto letter : substring) 
      the_set.insert(letter); 

Как было отмечено в комментариях, это будет перерыв, если word.size()>INT_MAX. Решение делает все в size_t (вы можете сделать все это в std::string::size_t, но это смешно многословно и на самом деле ничего не покупает).

dictionary<char, set<char>> near(const std::string word, size_t dist) { 
    dictionary<char, set<char>> map; 
    for (size_t x = 0; x < word.size(); x++) { 
     const auto start = (x > dist) ? x-dist : 0; // Beware underflow 
     const auto end = std::min(x+dist+1, word.size()); 
     const auto len = end - start; 
     const auto substring = word.substr(start,len); 
     auto &the_set = map[word[x]]; 
     for (const auto letter : substring) 
      the_set.insert(letter); 
    } 
} 

Эта версия имеет то преимущество, что НКУ будет компилировать его с -Werror -Wall (предыдущая версия будет жаловались на подпись/без знака сравнения), и не имеет бросок (всегда хороший знак).

Еще лучше было бы вариант, где start и end были итераторы в word - в какой момент вам не нужно будет создавать подстроку на всех (вы можете просто посмотреть на персонажей в оригинале слова).

+0

Моим вторым любимым ключевым словом является 'auto'; мой любимый - 'const'. Вы никогда не догадались, не так ли? –

+0

'std :: min (x + dist + 1, int (word.size());' это будет ломаться, если 'std :: string :: size_type' имеет больше max, чем' int' – NathanOliver

+0

Я думаю, что это будет только break, если 'word.size()' больше INT_MAX (что явно возможно только в том случае, если 'std :: string :: size_type' имеет большее значение max, чем' int', но это гораздо более сильное условие). также присутствует в исходном коде. –

Смежные вопросы