find position of a 2D vector which is an element of a class C++

I am working on a class that I have some problems in finding positions of values in one of elements of the class. I have defined my class as follows:

typedef class Chrom                                         
{
 public:
    vector<vector < int>> bit;                  
    vector<vector < bool>> jobisconsidered;

    vector<vector <float>> WaitingTime; 
    void variablesresize()
    {
        int i = 0, j, k;
        float a;

        std::vector<float> datapoints;
        std::ifstream myfile("Input.dat", std::ios_base::in);

        i = 0;                   //making zero counter of characters                        
        myfile.open("Input.dat");//now we reread numerical values                       

        while (!myfile.eof())
        {
            myfile >> a;
            //  cout << "i=" << i << '\n';              
            if (!myfile) // not an int                  
            {
                myfile.clear(); // clear error status               
                myfile.ignore(1); // skip one char at input             
            }
            else
            {
                datapoints.push_back(a);
                ++i;
            }
        }

        myfile.close();

        Jobs = datapoints[0];
        Machines = datapoints[1];

        WaitingTime.resize(Machines);
        bit.resize(Machines);

        for (int i = 0; i < Machines - 1; ++i)  WaitingTime[i].resize(Jobs);

        bit[i].resize(Jobs);
        }
    }
} c;

c popcurrent[50];

In the class, bit is a 2D element and if I define it as m*n, all values in the rows are the same. However, when I want to find position in bit, for example if popcurrent[0].bit for 2 rows and 3 columns is = { {3,2,1},{3,2,1} }, and I want to find position of the first "3" in the vector is 0 and popcurrent[0].bit[0][0]=3 , I have problems.

Specificaly I tried c++ search a vector for element first seen position with the following commands:

auto p = std::lower_bound(popcurrent[0].bit.begin(), popcurrent[0].bit.end(), 1);
int position = p - popcurrent[0].bit.begin();

But I get following error:

 Error  109 error C2893: Failed to specialize function template
'unknown-type std::less<void>::operator ()(_Ty1 &&,_Ty2 &&) const'

I know one way is to use for and if loops. But I wonder is there any more automated way to do this such as build in functions.

Upvotes: 1

Views: 1427

Answers (2)

JeJo
JeJo

Reputation: 32732

I want to find position of the first "3" in the vector is 0 and popcurrent[0].bit[0][0] = 3 , I have problems. Specificaly I tried c++ search a vector for element first seen position with the following commands:

auto p=std::lower_bound(popcurrent[0].bit.begin(), popcurrent[0].bit.end(), 1);
int position = p - popcurrent[0].bit.begin();

There are mainly two problems:

Problem - 1: std::lower_bound takes parameters first, last, which are forward-iterator types which defining the partially-ordered range. In your case(popcurrent[0].bit.begin()), you are passing a iterator which has the pointed element as a vector of integers (remember std::vector<std::vector<int>> is an array of vectors(vector<int>) not integers) for which std::lower_bound, could not find any definition for operator<. This is the reason of your error, where compiler complaining that:

" Hey, I don't have a specialisation for operator< your given range or vectors, to instantiate the template "

Problem - 2: You can not use std::lower_bound here, as it needs a strictly sorted array to binary search the value which has been provided. As you provided an unsorted vectors to check, the result won't be correct. See above link to read more:


Solution: You can use std::find_if which has a time complexity, up to linear in the distance between first and last iterator, according to the predicate provided, which will search for each element until a match is found. This could be an alternative if you do not want to sort each vector in the class, which is actually a 3-dimensional array of vectors.

Following is a sample solution: SEE LIVE HERE

#include <iostream>
#include <vector>
#include <algorithm>
#include <tuple>

typedef std::vector<std::vector < int>> Type ;
struct Chrom         // to demonstrate
{
  Type bit;
};

std::tuple<int, int, int> findPosition(const std::vector<Chrom>& vec3D, const int& val)
{
   int First = 0, Second = 0, Third = -1;   // initilize the positions
   for(const Chrom& each_chrom: vec3D)
   {
      for(const std::vector<int>& innerVec: each_chrom.bit)
      {
         std::vector <int>::const_iterator get_pos;
         get_pos = std::find(innerVec.cbegin(), innerVec.cend(), val);
         Third = (*get_pos == val) ? get_pos - innerVec.cbegin(): -1;   // check val found otherwise -1
         if(Third != -1) return std::make_tuple(First, Second, Third);  // if found return them
         ++Second;
      }
      Second = 0;
      Third = -1;
      ++First;
   }
   return std::make_tuple(First, Second, Third);
}

int main()
{
   // this is a 3 dimensional vector
   std::vector<Chrom> popcurrent(2);          //  position inside the popcurrent
   popcurrent[0].bit =  {  {3,2,1},           // (0,0,0) (0,0,1) (0,0,2)
                           {3,10,1}  };       // (0,1,0) (0,1,1) (0,1,2)
   popcurrent[1].bit =  {  {5,8,11},          // (1,0,0) (1,0,1) (1,0,2)
                           {4,7,1}  };        // (1,1,0) (1,1,1) (1,1,2)

   int pos_popcurrent, pos_bit, pos_inner_vec;
   for(int val = 1; val <= 12; ++val)
   {
      std::cout << "\nCurrently looking for: " << val ;
      std::tie(pos_popcurrent, pos_bit, pos_inner_vec) = findPosition(popcurrent, val);
      (pos_inner_vec != -1) ?
         std::cout << "  found @ popcurrent[ " << pos_popcurrent << " ].bit[ " << pos_bit << " ][ " << pos_inner_vec <<" ]":
         std::cout << "  Not found";
   }
   return 0;
}

Output:

Currently looking for: 1  found @ popcurrent[ 0 ].bit[ 0 ][ 2 ]
Currently looking for: 2  found @ popcurrent[ 0 ].bit[ 0 ][ 1 ]
Currently looking for: 3  found @ popcurrent[ 0 ].bit[ 0 ][ 0 ]
Currently looking for: 4  found @ popcurrent[ 1 ].bit[ 1 ][ 0 ]
Currently looking for: 5  found @ popcurrent[ 1 ].bit[ 0 ][ 0 ]
Currently looking for: 6  Not found
Currently looking for: 7  found @ popcurrent[ 1 ].bit[ 1 ][ 1 ]
Currently looking for: 8  found @ popcurrent[ 1 ].bit[ 0 ][ 1 ]
Currently looking for: 9  Not found
Currently looking for: 10  found @ popcurrent[ 0 ].bit[ 1 ][ 1 ]
Currently looking for: 11  found @ popcurrent[ 1 ].bit[ 0 ][ 2 ]
Currently looking for: 12  Not found

Upvotes: 1

joe_chip
joe_chip

Reputation: 2558

I didn't notice it at first - there's too much irrelevant code - but the problem is quite simple: you're trying to find the first element of type std::vector<int> not less than value of type int.

popcurrent[0].bit.begin() points to the first element of std::vector<std::vector<int>>, that is a vector. There's no "less than" operator for comparing a vector of ints and an int.

Upvotes: 3

Related Questions