Как получить элементы кортежа - PullRequest
0 голосов
/ 14 октября 2019

Я создаю игру в скрэббл, и мне нужно иметь базовую оценку слов в словаре.

Я использовал make_tuple и сохранил его в своем кортеже. Есть ли способ получить доступ к элементам в кортеже, как если бы он был в векторе?

#include <iostream>
#include <tuple>
#include <string>
#include <fstream>

void parseTextFile()
{
    std::ifstream words_file("scrabble_words.txt"); //File containing the words in the dictionary (english) with words that do not exist
    std::ofstream new_words_file("test.txt"); //File where only existing words will be saved
    std::string word_input;
    std::tuple<std::string, int> tupleList;

    unsigned int check_integrity;
    int counter = 0;

    while(words_file >> word_input)
    {
        check_integrity = 0;
        for (unsigned int i = 0; i < word_input.length(); i++)
        {
            if((int)word_input[i] >= 97 && (int)word_input[i] <= 123) //if the letter of the word belongs to the alphabet
            {
                check_integrity++;
            }
        }

        if(word_input.length() == check_integrity)
        {
            new_words_file << word_input << std::endl; //add the word to the new file
            tupleList = std::make_tuple(word_input, getScore(word_input)); //make tuple with the basic score and the word
            counter++; //to check if the amount of words in the new file are correct
            std::cout << std::get<0>(tupleList) << ": " << std::get<1>(tupleList) << std::endl;
        }
    }

    std::cout << counter << std::endl;
}

1 Ответ

1 голос
/ 14 октября 2019

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

В вашем случае то, чего вы хотите достичь, - это список пар слово-значение. Вы можете хранить их в контейнере, как вектор, но вы также можете хранить их в виде пар ключ-значение на карте . Как вы можете видеть при переходе по ссылке, std::map - это буквально набор объектов std::pair, а кортежи - это обобщение пар.

Для полноты, если мое понимание цели вашего кода верно, этиявляются дополнениями к вашему коду для хранения каждого кортежа в векторе - объявления,

   std::tuple<std::string, int> correct_word = {};
   std::vector<std::tuple<std::string, int>> existing_words = {};

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

 if(word_input.length() == check_integrity)
 {
    // ...
    correct_word = std::make_tuple(word_input, getScore(word_input)); 
    existing_words.push_back(correct_word);
    // ...
 }

.. и, наконец, пример использования вне цикла конструирования:

for (size_t iv=0; iv<existing_words.size(); ++iv)
{
    correct_word = existing_words[iv];
    std::cout << std::get<0>(correct_word) << ": " << std::get<1>(correct_word) << std::endl;
}
std::cout << counter << std::endl;

Тот же код с картой будет выглядеть так:

Единственным объявлением будет картаот строк до значений (вместо кортежа и вектора кортежей),

std::map<std::string, int> existing_words = {};

В цикле построения вы будете создавать пару карт в одной строке, например:

    if(word_input.length() == check_integrity)
    {
        // ...
        existing_words[word_input] = getScore(word_input);
        // ...
    }

В то время как после создания вы будете получать доступ к элементам карты, используя .first для слова и .second для счетчика. Ниже приведен пример печати, в котором также используется цикл for:

for (const auto& correct_word : existing_words)
    std::cout << correct_word.first << ": " << correct_word.second << std::endl;

    std::cout << counter << std::endl;

Обратите внимание, что карты по умолчанию упорядочены по алфавиту, вы можете указать собственные правила упорядочения, а также использовать неупорядоченную карту если вы не хотите упорядочивать / сортировать.

...