#c #algorithm #sorting #vector #std-pair
#c #алгоритм #сортировка #вектор #std-pair
Вопрос:
Моя задача — написать функцию, которая получает вектор строк в качестве аргумента и возвращает вектор pair<char,int>
, содержащий пары, представляющие символы и их частоту (сколько раз появлялась буква), суммированную из всех строк, переданных в vector в качестве аргумента функции. Он также должен быть отсортирован в порядке возрастания.
Приведенный ниже код — это мой подход к тому, как это сделать. Пока я могу только подсчитать, сколько раз символ встречается в каждой строке, но я не могу суммировать все встречающиеся буквы, чтобы получить одну пару.
#include <iostream>
#include <vector>
#include <utility>
#include <string>
using namespace std;
bool isEqual(const pair<char, int> amp;element) {
return element.first;
}
vector<pair<char, int>> all_occurrences(vector<string> vec) {
vector<pair<char, int>> sorted_vec;
vector<pair<char, int>> final_vec;
char c;
int count_chars = 0;
string element;
vector<char> check_chars = {' '};
bool char_found = false;
for (int i = 0; i < vec.size(); i ) {
element = vec[i];
for (int j = 0; j < element.length(); j ) {
c = element.at(j);
for (int k = 0; k < check_chars.size(); k) {
if (c == check_chars[k]) {
char_found = true;
break;
}
}
if (!char_found) {
check_chars.push_back(c);
count_chars = count(element.begin(), element.end(), c);
sorted_vec.push_back(make_pair(c, count_chars));
}
char_found = false;
}
check_chars = {' '};
}
vector<pair<char, int>>::iterator it;
for (int i = 0; i < sorted_vec.size(); i) {
it = find_if(sorted_vec.begin(), sorted_vec.end(), isEqual);
cout << it << endl;
}
return sorted_vec;
}
void print_vector(vector<pair<char, int>> pair_vector) {
cout << "---" << endl;
for (int i = 0; i < pair_vector.size(); i ) {
cout << pair_vector[i].first << ',' << pair_vector[i].second << endl;
}
cout << "---" << endl;
}
int main() {
vector<string> string_vector = {"ala", "ma", "kota"};
print_vector(all_occurrences(string_vector));
return 0;
}
Комментарии:
1. К вашему сведению, решение (код для
all_occurences
) составляет около 5 или 6 строк, если вы готовы использоватьstd::unordered_map
, и пару функций алгоритма STL.2. я, вероятно, немного растерялся из-за этого, потому что прошло буквально две недели. — И вы получили ответ в течение 10 минут. Не расстраивайтесь этим, поскольку мы ожидаем, что вы узнаете из данного ответа, а не просто скопируете его и передадите своему учителю.
3. @PaulMcKenzie Спасибо за разъяснение, я знаю, что здесь я могу попросить ответы на задачи, которые я еще не понимаю, — и я не ожидаю, что кто-нибудь позволит мне скопировать и вставить код без моего понимания. Гораздо приятнее, когда вы получаете ответ самостоятельно, но иногда его невозможно отменить, когда вы только начинаете. В любом случае, я проанализирую это подробнее и немного почитаю об этом, чтобы получить больше знаний об этом решении, которое кажется мне очень чистым.
Ответ №1:
Сначала вы можете вычислить все значения частоты с помощью std::map
:
std::map<char,int> m;
for(auto c : vec | std::views::join) // for every char in all strings
m[c] ;
Затем вы можете скопировать это map
в a vector
по мере необходимости:
vector<pair<char, int>> res;
std::ranges::copy(m, std::back_inserter(res));
И, наконец, вы можете отсортировать вектор в порядке возрастания количества частот:
std::ranges::sort(res, std::less{}, amp;std::pair<char, int>::second);
Вот демонстрация.
До C 20 вы можете написать приведенный выше код следующим образом:
Создайте счетчик частоты:
std::map<char,int> m;
for (auto const amp;s : vec) // for every string
for(auto c : s) // for every character
m[c] ; // add to the frequency count
Копировать в вектор:
vector<pair<char, int>> res;
std::copy(m.begin(), m.end(), std::back_inserter(res));
И отсортируйте его:
std::sort(res.begin(), res.end(), [](auto a, auto b) {
return a.second < b.second;
});
Вот демонстрация.
Комментарии:
1. Большое спасибо за ответ. Это именно то, что мне было нужно. И кажется, что использование map намного короче и экономичнее по времени, чем моя идея для этого. Как я уже сказал, я новичок в C , и до сих пор я программировал только на Java, поэтому я иногда теряюсь в синтаксисе и не всегда понимаю, для чего предназначены некоторые функции. Тем не менее, это отличный ответ, и он многое объясняет в функциональности map. Еще раз спасибо.
2. @Insekure Нет проблем, рад помочь 🙂 Как сказал Пол в комментарии выше, обязательно приложите усилия, чтобы понять решение и почему оно работает. Это будет действительно полезно в долгосрочной перспективе.
3. Я знаю, вот почему я здесь прошу помощи и лучших решений, а не просто прошу некоторых моих друзей сделать это за меня. Я хочу это понять, и я это сделаю — мне просто нужно немного почитать об этом и получить более глубокие знания. Еще раз спасибо.
4. @Insekure
auto
Это просто ярлык, но очень полезный. Вы также могли бы сделать это длинным путем, используя(const std::pair<char,int>amp; a, const std::pair<char,int>amp; b)
, но вы видите, насколько это длиннее.5. @Insekure КСТАТИ, в Java решение будет использовать тот же подход. «Список» для отслеживания символов и количества, аналогичный
std::map
, и скопировать результаты в массив для сортировки.