0

Here are my 2 structs to demonstrate my question. I have a table that has a vector of columns

struct column{
    string col_name;
    int index;
};

struct table{
   vector<vector<stuff>> rows;

   vector<column> columns;
};

What I want to do is search if one of my table objects has a column with string col_name I'm interested in.

I'm trying to use std::find, but I'm having a hard time putting the syntax together.

Say I have

  vector<table> all_tables;

How would I search a table (lets say table at index 0) to see if it contains bacon as the col_name?

So far I have

 find(all_tables[0].columns

And that's where I'm stuck. columns is a vector, and it wants an index, but I'm not sure what index to give. Do I just do columns.begin()? That doesn't seem to be correct since I have multiple member variables. I really want to be looking at the beginning of columns and the end of columns to find if it has the correct string (not int index) I'm interested in.

I understand the syntax for find is usually find(v.begin(), v.end(), "bacon"), but I don't know how to use it when it's in this scenario.

I would appreciate some help. Thank you!

----example-----

I have a table with 3 columns named "pie", "apple", and "bacon" respectively. So the size of vector columns is 3 inside my table struct. I want to be able to, given simply the table index, search through its column vector if it contains a column with the name I'm interested in.

MMM
  • 315
  • 1
  • 6
  • 19

1 Answers1

2

What you need is std::find_if - it allows you to specify any condition as a callable parameter instead of just a value to compare to:

std::find_if(all_tables[0].columns.begin(), all_tables[0].columns.end(),
             [](const column& c){ return c.col_name == "bacon";});

The last parameter here is a lambda that returns bool. find_if will apply it to all the columns in the range until it finds one that satisfies the condition in the lambda (c.col_name == "bacon").

You can pass any callable object instead of lambda here, e.g. std::function or you can define your own closure class, going with lambda is probably the most convinient way though.

Notice that std::find does the same thing as std::find_if, it just defaults to operator== as a condition, so another way to go is to define operator== for your class like this:

struct column{
    string col_name;
    int index;

    bool operator==(const column& c) const
    { return col_name == c.col_name; }

};

And then just use regular std::find():

column sample{"bacon"};
std::find(all_tables[0].columns.begin(), all_tables[0].columns.end(), sample);

Perhaps your column objects should be considered equal when their col_names are the same, then this second way could be preferable. Otherwise it's probably safer not to mess with operator==. This is up to you to decide, depending on your type logics.

Ap31
  • 3,244
  • 1
  • 18
  • 25