Как вставить вектор целых чисел в Key, значение std :: map - PullRequest
0 голосов
/ 26 августа 2018

Цель: Считать числовые текстовые файлы в векторы, а затем добавить векторы к ключу, значение std::map, чтобы я мог ссылаться на них по имени ключа, которое я указал для них позже.

Думаю, это будет легко, и я удивлен, что не могу найти ответ на этот вопрос уже в StackOverflow.

Ожидаемый результат :

Print1 = {100,200,500,600}

Print2 = {7890,5678,34567,3,56}

Print3["NameA"] = Print1

Print3["NameB"] = Print2

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

Я продолжаю получать сбой семантической проблемы, и нет жизнеспособного преобразования из pair <const basic_string>

Текущий код:

#include <string.h>
#include <iostream>
#include <map>
#include <utility>
#include <vector>

const std::string& key(const std::pair<std::string, std::string>& keyValue)
{
    return keyValue.first;
}

const std::string& value(const std::pair<std::string, std::string>& keyValue)
{
    return keyValue.second;
}

int main() 
{
    std::vector<int> print1;
    std::ifstream inputFile("numbers.txt");

    // test file open
    if (inputFile) 
    {
        double value; 
        // read the elements in the file into a vector
        while ( inputFile >> value ) {
            print1.push_back(value);
        }
    }
    inputFile.close();

    std::vector<int> print2;
    std::ifstream inputFile2("numbers2.txt");

    // test file open
    if (inputFile2) 
    {
        double value;              
        // read the elements in the file into a vector
        while ( inputFile2 >> value ) {
            print2.push_back(value);
        }
    }       
    inputFile2.close();

    std::map<std::string, std::vector<int>> contacts;   
    contacts["alice"] = print1;
    contacts["bob"] = print2;

    std::vector<std::string> keys(contacts.size());
    std::vector<int> values(contacts.size());

    transform(contacts.begin(), contacts.end(), keys.begin(), key);
    transform(contacts.begin(), contacts.end(), values.begin(), value);

    std::cout << "Keys:\n";
    copy(keys.begin(), keys.end(), std::ostream_iterator<std::string>(std::cout, "\n"));

    std::cout << "\n";

    std::cout << "Values:\n";
    copy(values.begin(), values.end(), std::ostream_iterator<std::string>(std::cout, "\n"));
    return 0;
}

Ответы [ 2 ]

0 голосов
/ 26 августа 2018

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

#include <iostream>
#include <fstream>
#include <map>
#include <vector>
#include <string>


int main()
{
    std::map<std::string, std::vector<int>> m;
    int num;

    auto &&alice = m["alice"];
    std::ifstream if_alice("numbers1.txt");

    while (if_alice >> num)
        alice.push_back(num);

    if_alice.close();

    auto &&bob = m["bob"];
    std::ifstream if_bob("numbers2.txt");

    while (if_bob >> num)
        bob.push_back(num);

    if_bob.close();

    // test
    for (auto &&data : m)
    {
        std::cout << "Name: " << data.first << "\t";
        for (int num : data.second)
            std::cout << num << " ";
        std::cout << "\n";
    }
}
0 голосов
/ 26 августа 2018

Прежде всего, нет смысла утверждать, что Xcode не отображал никаких сообщений об ошибках для вашего кода. Попробуйте либо включить все предупреждения компилятора, либо попробовать онлайн-компиляторы. Результат не разочарует: https://godbolt.org/z/cU54GX


Если я правильно понял, вы хотите сохранить вашу информацию из двух файлов (целочисленных значений) в std::map, где его ключ = std::string и значение = vector of integer array.

Если это так,

1 . У вас есть проблемы с чтением целых чисел из файлов. Там вы используете double без причины и сохраняете std::vector<int> (i, e print1 и print2).


2 . Во-вторых, что если ваш файл не был открыт? inputFile.close(); и inputFile2.close(); все равно закроет его, не зная факт. Это не верно. Правильный путь будет:

inputFile.open("numbers.txt", std::ios::in); // opening mode
if (inputFile.is_open()) { 
   // do stuff
   inputFile.close(); // you need closing only when file has been opened
}

3 . Если вы собираетесь печатать только keys и values, вы не нужно разобрать их по разным векторам. Вы можете сделать это напрямую:

for(const std::pair<kType, vType>& mapEntry: contacts)
{
    std::cout << "Key: " << mapEntry.first << "   Values: ";
    for(const int values: mapEntry.second) std::cout << values << " ";
    std::cout << std::endl;
}

В c ++ 17 вы можете использовать Структурированное связывание

for(const auto& [Key, Values]: contacts)
{
    std::cout << "Key: " << Key << "   Values: ";
    for(const int value: Values) std::cout << value << " ";
    std::cout << std::endl;
}

4 . Если вы действительно хотите разобрать их в другом векторе; Прежде всего, структура данных для хранения keys неверна:

std::vector<int> values(contacts.size());
          ^^^^^^

который должен был быть вектором целых чисел, как ваш vType = std::vector<int>. То есть

std::vector<std::vector<int>> values
           ^^^^^^^^^^^^^^^^^^

Во-вторых, у вас неправильные функции key(const std::pair<std::string, std::string>& keyValue) и value(const std::pair<std::string, std::string>& keyValue), когда вы передаете пару строк в качестве ключей и значений.

Это должно было быть

typedef std::string    kType;  // type of your map's key
typedef std::vector<int> vType;// value of your map's value
std::pair<kType, vType>

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

std::vector<kType> keysVec; 
keysVec.reserve(contacts.size());
auto getOnlyKeys   = [](const std::pair<kType, vType>& mapEntry){  return mapEntry.first; };
std::transform(contacts.begin(), contacts.end(), std::back_inserter(keysVec), getOnlyKeys);

См. Пример кода здесь

...