C ++ Соединение двух разделенных на трубы файлов по ключевым полям

0

В настоящее время я пытаюсь создать функцию C++, чтобы объединить два файла с разделенными каналами с более чем 10.000.000 записей в одном или двух ключевых полях.

Филе выглядят как



    P2347|John Doe|C1234
    P7634|Peter Parker|D2344
    P522|Toni Stark|T288

а также



    P2347|Bruce Wayne|C1234
    P1111|Captain America|D534
    P522|Terminator|T288

Чтобы присоединиться к полям 1 и 3, ожидаемый результат должен показывать:



    P2347|C1234|John Doe|Bruce Wayne
    P522|T288|Toni Stark|Terminator

То, о чем я сейчас думаю, использует set/array/vector для чтения в файлах и создает что-то вроде:



    P2347|C1234>>John Doe
    P522|T288>>Toni Stark

а также



    P2347|C1234>>Bruce Wayne
    P522|T288>>Terminator

И затем используйте проскальзывание первой части в качестве ключа и сопоставьте ее со вторым набором/вектором/массивом.

В настоящее время у меня есть: Прочитайте в первом файле и сопоставьте второй файл по строкам с набором. Он берет всю строку и сопоставляет ее:



    #include iostream>
    #include fstream>
    #include string>
    #include set>
    #include ctime>
    using namespace std;

    int main()
    {

        clock_t startTime = clock();

        ifstream inf("test.txt");
        set lines;
        string line;
        for (unsigned int i=1; std::getline(inf,line); ++i)
            lines.insert(line);

        ifstream inf2("test2.txt");

        clock_t midTime = clock();

        ofstream outputFile("output.txt");  
        while (getline(inf2, line))
        {
            if (lines.find(line) != lines.end())
                outputFile > a;
        return 0;

}

Я очень рад за любое предложение. Я также счастлив изменить всю концепцию, если есть лучший (более быстрый) способ. Скорость критическая, так как может быть даже более 10 миллионов записей.

EDIT: Еще одна идея - взять карту и ключом будет ключ, но это может быть немного медленнее. Какие-либо предложения?

Большое спасибо за любую помощь!

Теги:
arrays
join
vector
ifstream

1 ответ

0

Я попробовал несколько способов, чтобы эта задача была завершена, ни одна из них не была эффективной:

Прочитайте все в наборе и проанализируйте ключевые поля в формате: ключи >> значения, моделирующие набор типов массива. Парсинг занимал много времени, но использование памяти остается относительно низким. Не полностью разработан код:



        #include \
        #include \
        #include \
        #include \
        #include \
        #include \
        #include \
        std::vector &split(const std::string &s, char delim, std::vector &elems) {
        std::stringstream ss(s);
        std::string item;
        while (std::getline(ss, item, delim)) {
            elems.push_back(item);
        }
        return elems;
    }


    std::vector split(const std::string &s, char delim) {
        std::vector elems;
        split(s, delim, elems);
        return elems;
    }

    std::string getSelectedRecords(std::string record, int position){

        std::string values;
        std::vector tokens = split(record, ' ');




        //get position in vector
        for(auto& s: tokens)
            //pick last one or depending on number, not developed
            values = s;

        return values;
    }

    int main()
    {

        clock_t startTime = clock();

        std::ifstream secondaryFile("C:/Users/Batman/Desktop/test/secondary.txt");
        std::set secondarySet;
        std::string record;

        for (unsigned int i=1; std::getline(secondaryFile,record); ++i){
            std::string keys = getSelectedRecords(record, 2);
            std::string values = getSelectedRecords(record, 1);
            secondarySet.insert(keys + ">>>" + values);
        }

        clock_t midTime = clock();

        std::ifstream primaryFile("C:/Users/Batman/Desktop/test/primary.txt");
        std::ofstream outputFile("C:/Users/Batman/Desktop/test/output.txt");

        while (getline(primaryFile, record))
        {
            //rewrite find() function to go through set and find all keys (first part until >> ) and output values
            std::string keys = getSelectedRecords(record, 2);

            if (secondarySet.find(keys) != secondarySet.end())
                outputFile > a;
        return 0;
        }

Вместо того, чтобы делиться трубой, в настоящее время используется разделенное пространство, но это не должно быть проблемой. Чтение данных происходит очень быстро, но синтаксический анализ занимает очень много времени

Другой вариант - использовать мультимап. Аналогичная концепция с ключевыми полями, указывающими на значения, но эта очень низкая и интенсивная память.



    #include \
    #include \
    #include \
    #include \
    #include \
    #include \
    #include \

    int main()
    {


    std::clock_t startTime = clock();

    std::ifstream inf("C:/Users/Batman/Desktop/test/test.txt");
    typedef std::multimap Map;
    Map map;

    std::string line;

    for (unsigned int i=1; std::getline(inf,line); ++i){
        //load tokens into vector
        std::istringstream buffer(line);
        std::istream_iterator beg(buffer), end;
        std::vector tokens(beg, end);
        //get keys
        for(auto& s: tokens)
            //std::cout >>" second;
            outputFile > a;
    return 0;
    }

Дальнейшие мысли: разделение файлов разделенных труб на разные файлы с одним столбцом справа при импорте данных. При этом мне не придется разбирать что-либо, но может читать в каждом столбце отдельно.

EDIT: оптимизирован первый пример с помощью функции рекурсивного разделения. Еще> 30 секунд для 100 000 записей. Хотелось бы увидеть, что быстрее и фактическая функция find() по-прежнему отсутствует.

Есть предположения? Благодарю!

Ещё вопросы

Сообщество Overcoder
Наверх
Меню