2014-10-13 2 views
-1

У меня есть вектор, который содержит буквенно-цифровую строку, и я хочу отсортировать вектор на основе числового значения.сортировка буквенно-цифровой строки с использованием вектора

Например, если мой вектор содержит следующие значения:

NAME0 name20 name15 name3 name10, мой отсортированный вектор должен выглядеть следующим образом:

NAME0 name3 name10 name15 namw20.

Может ли кто-нибудь помочь, как это сделать ..? Вот мой полный код:

#include<vector> 

#include<string> 
#include <cstdlib> 

#include <algorithm> 
#include <iostream> 
using namespace std; 

int main() 
{ 
     vector<string> temp; 
     temp.push_back("name0"); 
     temp.push_back("name20"); 
     temp.push_back("name15"); 
     temp.push_back("name3"); 
     temp.push_back("name10"); 

     sort(temp.begin(), temp.end()); 


     for (vector<string>::size_type i = 0; i!= temp.size(); i++) 
       cout << temp[i] << endl; 


return 0; 
} 
+0

Вам нужно разбить строку на токены на основе строк и чисел, а затем выполнить лексикографическое сравнение по одному токену за раз. – shuttle87

ответ

1

Предполагая, что C++ 11, вы можете использовать лямбда и std::stoi преобразовать действительные части строк для цифр.

sort(temp.begin(), temp.end(), [] (const std::string& a, const std::string& b) { 
    std::string cmp_a { a.begin() + 4, a.end() }; 
    std::string cmp_b { b.begin() + 4, b.end() }; 
    return std::stoi(cmp_a) < std::stoi(cmp_b); 
}); 

Конечно, std::stoi бросят, если преобразование не удается, поэтому убедитесь, что строки вы передаете ему содержать только цифры.


В C++ 03, вы можете использовать Boost.Lexical_Cast:

int convert(const std::string& s, std::size_t pos) 
{ 
    return boost::lexical_cast<int>(s.data() + pos, 
     std::distance(s.begin() + pos, s.end())); 
} 

bool predicate(const std::string& a, const std::string& b) 
{ 
    return convert(a, 4) < convert(b, 4); 
} 

Как отмечено в комментарии, 4 является жестко закодированным положение, в котором происходит первая цифра. Если она изменяется, вы можете использовать find_first_of:

const std::string numbers = ""; 

bool predicate(const std::string& a, const std::string& b) 
{ 
    std::size_t a_start = a.find_first_of(numbers); 
    std::size_t b_start = b.find_first_of(numbers); 
    return convert(a, a_start) < convert(b, b_start); 
} 

Гораздо лучше ответ уже написан Charles Salvia (который не зависит от усиления или C++ 11). Он ссылается на страницу, которая реализует natural sorting order, как упоминалось в другом комментарии.

+0

спасибо remyabel. Не могли бы вы объяснить, почему вы использовали + 4 здесь: std :: string cmp_a {a.begin() + 4, a.end()}; – user3527124

+0

@ user3527124 4 символа в «имени». Если это может измениться, вам нужно будет найти первый цифровой символ. –

+0

Думаю, я ответил на свой вопрос ...? Это потому, что name0, name20 и т. Д.? a.begin + 4 будет указывать на первое числовое значение после строки «name». верный..? – user3527124