Thread: search for values from one file into another

  1. #1
    Registered User
    Join Date
    Jan 2017
    Posts
    4

    search for values from one file into another

    I have two .txt files. The 1st file has number and state, the second file has number and a number value. If there are matches between the numbers in 1st file and 2nd file the program saves

    case 1: 1st file number,second file number, associated value and 1 .

    if there is no match, the program saves

    case 2 :1st file number,second file number, associated value and 0 in a .csv file

    the first case is working , but second case is showing the required result , thanks for help


    Code:
    #include <iostream>
    #include <fstream>
    #include <string>
    #include <map>
    
    int main ()
    {
        int number = 0;
        double value = 0;
        std::string state;
    
        std::map<int, std::string> map_f1;
        std::map<int, double> map_f2;
        std::map<int,double>::iterator it2;
    
        std::ifstream file1 ("1st_file.txt");
        std::ifstream file2 ("2nd_file.txt");
        std::ofstream out_true_ear ("out_ture_positive_ear_values.csv");
    
    
        if ( file1.is_open() and file2.is_open() )
            {
                while ( file1 >> number >> state )
                    map_f1[number] = state;
                file1.close();
    
                while ( file2 >> number >> value )
                    map_f2[number] = value;
                file2.close();
    
                for(auto it1 = map_f1.begin(); it1 != map_f1.end(); it1++)
                    {
                        it2 = map_f2.find( it1 -> first);
                        if (it2 != map_f2.end())
                            out_true_ear<<"1st_file"<<","<< it1 -> first << "," <<"2nd_file "<< ","<<it2 -> first << "," << it2 -> second <<","<< 1<<'\n';
                        else
                            out_true_ear<<"1st_file"<<","<< it1 -> first << ","<< "2nd_file"<<"," << it2 -> first << "," << it2 -> second <<","<< 0<<'\n';
                    }
            }
        else
            std::cout << "Unable to open file1 and/or file2\n";
    
        return 0;
    }

  2. #2
    Lurking whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    9,613
    If the numbers do not match, it means that map_f2 does not have a corresponding value for that key, in which case, you cannot write it2->first or it2->second. You will end up causing a segmentation fault.

    There is a way to do this as completely as possible, but you will end up with some empty fields.
    Code:
    for (auto& it : map_f1) 
    { 
       if (map_f2.count(it->first) != 0) { // number is a key in both maps
          out_true_ear << "1st_file," << it->first << "," << it->second << ",2nd_file," << it->first << "," << map_f2[it->first] << "," << 1 << "\n";
       else // number is NOT A KEY in both maps
          out_true_ear << "1st_file," << it->first << "," << it->second << ",2nd_file,,," << 0 << "\n";
    }
    The above code will output all of the key-value pairs that map_f1 has, and also the map_f2 key-value pairs, if map_f2 uses the same key as map_f1.

    If you also want to print the key-value pairs that are unique to map_f2, you can use the call map_f1.count(it2->first) in a similar loop to figure out which keys to ignore.

    I'm not sure what you want.

    HTH.
    Last edited by whiteflags; 01-13-2017 at 09:58 PM.

  3. #3
    Registered User
    Join Date
    Jan 2017
    Posts
    4
    I will give you an example of what I'm trying to do

    if 1st file have these data

    380 close
    470 close
    510 close

    and 2nd file have these data :

    90 0.234
    380 0.456
    381 0.283
    400 0.763
    470 0.765
    500 0.865
    510 0.765

    The required output is :

    90 0.234 0

    380 close 380 0.456 1

    381 0.283 0

    400 0.763 0

    470 close 470 0.765 1

    500 0.865 0

    510 close 510 0.765 1


    The code I provided is showing the match case between 1st and 2nd file and saving 1 in the .csv file .

    I'm having problem with the second case if there is no match .
    Last edited by toficeos; 01-14-2017 at 09:30 AM.

  4. #4
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,660
    There's no need to store the second file in anything. You can just look-up and print as you go.
    Code:
                while ( file1 >> number >> state )
                    map_f1[number] = state;
                file1.close();
                
                while ( file2 >> number >> value ) {
                  it1 = map_f1.find(number);
                  if ( it1 != map_f1.end() ) {
                    std::cout << number << ","
                         << it1->second << ","
                         << number << ","
                         << value << ","
                         << "1" << std::endl;
                  } else {
                    std::cout << number << ","
                         << value << ","
                         << "0" << std::endl;
                  }
                }
                file2.close();
    
    ...
    
    $ g++ foo.cpp
    $ ./a.out 
    90,0.234,0
    380,close,380,0.456,1
    381,0.283,0
    400,0.763,0
    470,close,470,0.765,1
    500,0.865,0
    510,close,510,0.765,1
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  5. #5
    Registered User
    Join Date
    Jan 2017
    Posts
    4
    Thanks for help, now it is solved

    Regards

  6. #6
    Registered User
    Join Date
    Jan 2017
    Posts
    4
    HI

    I have made some changes as below:

    the 1st .txt file contains two cols .

    number and state e.g :

    number state

    378 close
    408 close
    509 close

    and I have 2nd .txt file contains numbers and corresponding values e.g:

    number value
    1 0.345
    2 0.234
    3 0.236
    . .
    . .
    15832

    I done the first part which is to search for the numbers from the first file in the second file . for example search for (372,408 and so on ) in the second file , and if found take 13 numbers ( 6 before the number and 6 after ) together with their values from the second file example ,

    380 is in the first file , the program found 382 in the second file so it will take 13 number and value

    380 found in the second file :

    374 0.681042
    375 0.69153
    376 0.702018
    377 0.712506
    378 0.722994
    379 0.733482
    380 0.74397
    381 0.754458
    382 0.764946
    383 0.775434
    384 0.785922
    385 0.79641
    386 0.74541


    I need to display the other case , if there is no match between the numbers in 1st and 2nd file , just display the not matching case (i.e 2nd file number and value ) without taking +6,-6 .

    the code below is saving the matching case with +6,-6 but not showing if there is no match.


    Code:
    #include <iostream>
    #include <fstream>
    #include <string>
    #include <map>
    
    #include <vector>
    
    
    int main ()
    {
        int number = 0;
        double value = 0;
        std::string state;
        int key = 0;
    
        std::map<int, std::string> map_f1;
        std::map<int, double> map_f2;
        std::map<int,double>::iterator it2, it3;
    
     std::ifstream file1 ("blink8_v1_close.txt");
        std::ifstream file2 ("EAR_LEFT_v1.txt");
        std::ofstream out;
        std::vector<double>  vec_f2;
    
        out.open("13_EAR_LEFT_v1.csv");
    
        if ( file1.is_open() and file2.is_open() )
        {
            while ( file1 >> number >> state )
                map_f1[number] = state;
            file1.close();
    
    
            int nextnumber = 0;
            while ( file2 >> number >> value )
            {
                // fill gaps with -1.0
                if (number > nextnumber)
                {
                       vec_f2.insert(vec_f2.end(), number - nextnumber ,-1.0);
                       nextnumber = number;
                }
                if (number == nextnumber)
                {
                    vec_f2.push_back(value);
                    nextnumber++;
                }
            }
            file2.close();
    
    
    
    
    
        int maxnum = (int)vec_f2.size();
            for(auto it1 = map_f1.begin(); it1 != map_f1.end(); it1++)
            {
                if (it1 -> first > 0 && it1->first < maxnum)
                {
                    // Display linked item
                    out << it1 -> first << "," << it1 -> second << ","  << vec_f2[it1 -> first] << '\n';
    
                    // Display previous 6 and following 6
                    key = it1 -> first;
                    for( int i =std::max(0, key - 6); i < std::min(key + 7, maxnum); i++)
                    {
                        if (vec_f2[i] > 0.)
                        {
                        out <<"," <<i << ","<<vec_f2[i]<< '\n';
                        }
                    }
                }
                
                
            }
        }
    
        else
            std::cout << "Unable to open file1 and/or file2\n";
    
    
    
    
    
        return 0;
    }
    Last edited by toficeos; 01-18-2017 at 04:35 AM.

  7. #7
    Lurking whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    9,613
    I think I understand what you're trying to do. You can still read file2 as you go.

    What matters is if the number is in your current range or not, and where you should put the number-value pair. You should just print numbers and values that are below your range. If the number is in the current range, it means you can save the number and value to a stringstream in order to put it in the file later, when you find the exact number in file2. When the number is higher than your current range, you should advance the map, and figure out what to do with the current number. It is either in the new range or not.

    I wrote a function for it:
    Code:
    #include <iostream>
    #include <fstream>
    #include <algorithm>
    #include <numeric>
    #include <string>
    #include <sstream>
    #include <map>
    using namespace std;
    
    void MakeOutput(string fileName, const map<int, string>& mapf1, ostream& out)
    {
        ifstream file(fileName);
        if (file.is_open())
        {
            map<int, string>::const_iterator it = mapf1.begin();
            map<int, string>::const_iterator End = mapf1.end();
            int lo = max(0, it->first - 6);
            int hi = 6 + it->first;
    
    
            int number;
            double value;
            ostringstream collector;
            while (file >> number >> value)
            {
                if (number < lo)
                {
                    //Display numbers below our range
                    out << number << "," << value << endl;
                }
                else if (lo <= number && number <= hi)
                {
                    if (number == it->first)
                    {
                        //Display linked value
                        out << number << "," << it->second << "," << value << endl;
                    }
                    //Collect values in our range
                    collector << number << "," << value << ",";
                }
                else
                {
                    // Display collected values.
                    string coll = collector.str();
                    if (!coll.empty())
                    {
                        coll.pop_back(); // Remove the extra comma
                        out << coll << endl;
                        collector.str("");
                    }
    
    
                    // Advance the map
                    if (it != End && ++it != End)
                    {
                        lo = max(0, it->first - 6);
                        hi = 6 + it->first;
                    }
                    else
                    {
                        //lo needs to be high to capture any leftovers in file2.
                        lo = numeric_limits<int>::max();
                    }
    
    
                    // Handle the current number with the new range.
                    if (lo <= number && number <= hi)
                    {
                        collector << number << "," << value << ",";
                    }
                    else
                    {
                         out << number << "," << value << endl;
                    }
                }
            }
        }
        else
        {
            cout << "Couldn\'t open file 2: " << fileName << endl;
        }
    }
    
    371,0.4
    378,close,0.691
    372,0.123,373,0.239,374,0.759,375,0.774,376,0.748,377,0.675,378,0.691,379,0.272,380,0.502,381,0.969,382,0.921,383,0.173,384,0.679
    385,0.601
    386,0.578
    387,0.476
    388,0.998
    389,0.777
    390,0.952
    391,0.554
    392,0.998
    393,0.972
    394,0.053
    395,0.294
    396,0.742
    397,0.179
    398,0.689
    399,0.885
    400,0.026
    401,0.644
    408,close,0.41
    402,0.13,403,0.131,404,0.429,405,0.86,406,0.702,407,0.309,408,0.41,409,0.674,410,0.957,411,0.886,412,0.664,413,0.604,414,0.867
    415,0.294
    416,0.647
    417,0.386
    418,0.463
    419,0.667
    420,0.461
    :
    :
    Pretty clean solution I think, as long as it's correct.
    Last edited by whiteflags; 01-19-2017 at 09:03 PM.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 2
    Last Post: 02-03-2015, 10:19 AM
  2. Word Search problem, runtime error, not getting right values.
    By Jordan Rauscher in forum C Programming
    Replies: 20
    Last Post: 09-26-2012, 11:11 PM
  3. search file for values in lookup table
    By sixstringsgaret in forum C Programming
    Replies: 12
    Last Post: 03-04-2008, 04:23 PM
  4. Search a file for a value by key
    By fredanthony in forum C Programming
    Replies: 2
    Last Post: 01-16-2007, 10:50 PM
  5. file search
    By Hypercase in forum C++ Programming
    Replies: 3
    Last Post: 02-05-2005, 05:04 AM

Tags for this Thread