2017-02-22 68 views
-2

У меня есть vector<string>, содержащий несколько слов, которые основаны на пользовательском вводе. Все они хранятся в векторе, используя переменную с именем container. Мне нужно расположить слова в строке в нетрадиционным QWERTY-заказа, или другими словами, мне нужно, чтобы они были отсортированы на основе строки string sequence = "QWERTYUIOPASDFGHJKLZXCVBNM"; Так пример запуска будет выглядеть следующим образомЕсть ли способ сравнить вектор с последовательностью строк, используя сортировку?

Enter a word: apple Enter a word: pear Enter a word: peach

Words sorted in QWERTY order: pear peach apple

Я в настоящее время только в состоянии хранить эти строки символов, и так как они не в алфавитном порядке, я не могу использовать символьные значения, если-заявление,

я заикнулся использовать сортировку отбора или вставка для сравнения моей векторной строки с QWERTY-последовательностью, но я не могу найти какие-либо примеры в своем учебнике или в Интернете о том, как применить это к моему коду. Любая помощь будет принята с благодарностью, спасибо за ваше время.

+0

Вам не нужен какой-либо выбор. Это очень простая таблица поиска, чтобы найти символ, соответствующий строке qwerty. Также, пожалуйста, выберите язык, C или C++. Решение C++ - это две строки, возможно одна. – PaulMcKenzie

+0

Извините, я не привык к навигации по этому сайту, и я думаю, что неправильно ввел теги. Я не понимаю, что вы подразумеваете под поисковой таблицей, есть ли хорошая ссылка, на которую я могу смотреть? – laura

+0

Подумайте, вне коробки. Что, если «myword» - «PEAR». Что будет 'sequence [myword [0]]', 'sequence [myword [1]]', 'sequence [myword [2]]',, 'sequence [myword [3]]'? Таким образом, в вашем роде вы сравниваете значения массива последовательностей, используя символы «PEAR» в качестве поиска. – PaulMcKenzie

ответ

0

Просто использовать std::string::find найти индекс символа и сравнить их:

bool sequenceLess(const std::string &s1, const std::string &s2) 
{ 
    static const std::string sequence = "QWERTYUIOPASDFGHJKLZXCVBNM"; 
    for(size_t i = 0; i < s1.length(); ++i) { 
     if(i >= s2.length()) return false; 
     auto idx1 = sequence.find(::toupper(s1[i])); 
     auto idx2 = sequence.find(::toupper(s2[i])); 
     if(idx1 == idx2) continue; 
     return idx1 < idx2; 
    } 
    return true; 
} 

другой вариант, чтобы преобразовать строку в вектор индексов и их сравнения:

std::vector<size_t> convert(const std::string &s) 
{ 
    static const std::string sequence = "QWERTYUIOPASDFGHJKLZXCVBNM"; 
    std::vector<size_t> r(s.size()); 
    std::transform(s.begin(), s.end(), r.begin(), [sequence](char c) { 
     return sequence.find(::toupper(c)); 
    }); 
    return r; 
} 

// now comparison is obvious 
bool sequenceLess(const std::string &s1, const std::string &s2) 
{ 
    return convert(s1) < convert(s2); 
} 

Это решение неэффективно, но для обучения p Указать должно быть хорошо.

0

Один из вариантов заключается в замене каждого символа на соответствующий из вашего специального алфавита. Затем сделайте вид и перейдите обратно.

Например:

we -> bc, er -> cd 
+0

Назначить каждому персонажу какую-то ценность? Как я могу применить функцию сортировки к этому? – laura

+0

Я понимаю, что вы имеете в виду, но мне не нужен цикл для каждой буквы алфавита? Если я их назначу, значения разных букв не будут печататься неправильно? – laura

0

Вы можете попробовать подобрать сортировку. Пожалуйста, обратитесь к этой ссылке Sorting a vector of custom objects

Ниже приведен пример моего кода для вашего случая, но я обрабатываю дескриптор для строчных букв.

#include<iostream> 
#include<vector> 
#include<algorithm> 

using namespace std; 

struct mySort{ 
    inline bool operator() (const string& s1, const string& s2) 
    { 
     bool isSort = false; 

     if(s1.length() < s2.length()){ 
      return true; 
     }else if(s1.length() > s2.length()){ 
      return false; 
     } 

     //s1.length() == s1.length() 
     string sequence = "QWERTYUIOPASDFGHJKLZXCVBNM"; 
     int index1 = 0 , index2 = 0; 
     for(int i = 0 ; i < s1.length() ; i++){ 

      for(int j = 0 ; j < sequence.length() ; j++){ 
       if(s1[i] == sequence[j]){ 
        index1 = j; 

       } 
       if(s2[i] == sequence[j]){ 
        index2 = j; 
       } 
      } 

      if(index1 < index2){return true;} 
     } 

     return false; 
    } 
}; 

int main(){ 


    vector<string> myVector; 
    myVector.push_back("APPLE"); 
    myVector.push_back("PEAR"); 
    myVector.push_back("PEACH"); 
    sort(myVector.begin(), myVector.end(), mySort()); 
    for(int i = 0 ; i < myVector.size() ; i++){ 
     cout<<myVector[i]<<endl; 
    } 

    return 1; 
} 

Вот результат,

enter image description here

PS: Может быть, мне не хватает некоторых условий, а просто поделиться с вами, как применить подгоняем вид.

+0

Это стиль кода, который я привык видеть, поэтому я думаю, что я могу понять его немного лучше. Однако я немного смущен, так как в этом случае слова «подчиняющиеся» и «высшие» неправильно сортируются в порядке qwerty, – laura

+0

Поскольку я устанавливаю приоритет длины выше, чем последовательность, subdue короче, чем выше, поэтому он будет приходи первым. [PS: Убедитесь, что вы запишете как заглавную букву] –

+0

Кстати, это всего лишь образец кода, чтобы показать вам, как это работает. Вы можете создать свое собственное условие сортировки внутри структуры, надеюсь, что мой обмен полезен. –

0

Вы можете перегрузить < оператора для строк, а затем использовать C++ функцию sort(), расположенный в <algorithm> я не совсем понимаю, как вы точно хотите отсортировать строки с этим правилом, так что до вас, чтобы закодировать сравнение двух строки, и это было бы так.

0

Редактировать: добавлена ​​таблица поиска и исправлены тесты в getless.

Вот еще одно решение, используя зЬй :: сортировку и функцию, которая проверяет каждую строку и возвращает true если одна строка меньше другой, чтобы QWERTY:

#include <algorithm> 
#include <string> 
#include <vector> 
#include <cctype> 
#include <iostream> 

typedef std::vector<std::string> StringVect; 
std::string sequence = "QWERTYUIOPASDFGHJKLZXCVBNM"; 
std::vector<int> lookup(26); 

bool getless(const std::string& s1, const std::string& s2) 
{ 
    for (size_t i = 0; i < std::min(s1.size(), s2.size()); ++i) 
     if (s1[i] != s2[i]) 
      return (lookup[toupper(s1[i])-'A'] < lookup[toupper(s2[i])-'A']); 
    return s1.size() < s2.size(); 
}; 

int main() 
{ 
    StringVect sv = {{ "apple" },{ "pear" },{ "peach" }}; 

    // build the lookup table 
    int i = 0; 
    std::for_each(sequence.begin(), sequence.end(), [&](char ch) {lookup[ch-'A'] = i; ++i; }); 

    // sort the data 
    std::sort(sv.begin(), sv.end(), getless); 

    // output results 
    for (auto& s : sv) 
     std::cout << s << "\n"; 
} 

Live Example

таблице перекодировки , который сопоставляет относительную позицию ASCII символа, где символ находится в строке sequence. Так, например, lookup[0] позиция A (который является 10), lookup[1] позиция B (который является 23) и т.д.

getless функция сканирует строку и проверяет характер, связанный с характером i'th каждая строка с соответствующей позицией поиска.

Цикл for в основном «ждет» отличия символов в сравнении двух строк. Если символ в строке для s1 имеет значение поиска меньше, чем значение поиска для символа в s2, тогда мы немедленно возвращаем «истину», что означает, что s1 < s2. В противном случае мы возвращаем false, если s1> s2.

Если символы равны, мы продолжаем цикл, пока не закончим сравнение символов. Если обе строки равны до точки, мы выходим из цикла for, мы возвращаем true или false, в зависимости от длины строк (более короткая строка будет означать s1 < s2).

+0

Вы заметили, что ваш живой пример получает неправильный ответ? Желаемый результат - груша

+0

Сравнение 'sequence [toupper (s1 [i]) - 'A']

+0

@FrankBoyne Я понял ошибку и исправил пример. На самом деле было две проблемы: одна с таблицей поиска и что функция должна возвращать меньшую длину двух строк, если цикл заканчивается, не возвращая true или false в функции 'getless'. – PaulMcKenzie