Search a vector of objects by object attribute
You can use std::find_if
with a suitable functor. In this example, a C++11 lambda is used:
std::vector<Type> v = ....;
std::string myString = ....;
auto it = find_if(v.begin(), v.end(), [&myString](const Type& obj) {return obj.getName() == myString;})
if (it != v.end())
{
// found element. it is an iterator to the first matching element.
// if you really need the index, you can also get it:
auto index = std::distance(v.begin(), it);
}
If you have no C++11 lambda support, a functor would work:
struct MatchString
{
MatchString(const std::string& s) : s_(s) {}
bool operator()(const Type& obj) const
{
return obj.getName() == s_;
}
private:
const std::string& s_;
};
Here, MatchString
is a type whose instances are callable with a single Type
object, and return a boolean. For example,
Type t("Foo"); // assume this means t.getName() is "Foo"
MatchString m("Foo");
bool b = m(t); // b is true
then you can pass an instance to std::find
std::vector<Type>::iterator it = find_if(v.begin(), v.end(), MatchString(myString));
Find if an object attribute is in the Vector of objects C++
In your situation std::find_if could be the solution
auto it = find_if(c.begin(), c.end(), [&check](const Car& obj) {return obj.getDir() == check;})
find a value in a vector of class objects
I found two solution as for my problem:
You can implement std::find in vector class-based object in c++:
class A {
private:
string b;
string c;
public:
A(string i) : b(i) {}
A(string n, string l) { b = n ;c = l; }
string Getb(){ return b; }
string Getc(){ return c; }
bool operator==(const A & obj2) const
{
return (this->b.compare(obj2.b) == 0);
}
};
int main()
{
vector<A> a1;
a1.push_back(A("AA","aa"));
a1.push_back(A("BB","bb"));
a1.push_back(A("CC","cc"));
a1.push_back(A("DD","dd"));
auto it = find(a1.begin(), a1.end(), A("CC"));
if (it != a1.end()) {
auto idx = distance(a1.begin(), it);
cout << "b= " << it->Getb() << " c= " << it->Getc() << endl;
cout << "Index= " << idx << endl;
} else
cout << "CC is not found" << endl;
return 0;
}You can implement std::find_if in vector class/structure based object in c++ (thanks to @Vlad from Moscow and @R Sahu):
class A {
private:
string b;
string c;
public:
A(string n, string l) { b = n ;c = l; }
string Getb(){ return b; }
string Getc(){ return c; }
struct Finder {
Finder(string const & n) : name(n) { }
bool operator () (const A & el) const {
return el.Pos == name;
}
string name;
};
};
int main()
{
vector<A> a1;
a1.push_back(A("AA","aa"));
a1.push_back(A("BB","bb"));
a1.push_back(A("CC","cc"));
a1.push_back(A("DD","dd"));
vector<A>::iterator it;
it = find_if(a1.begin(), a1.end(), A::Finder ("CC"));
if (it != a1.end()) {
auto idx = distance(a1.begin(), it);
cout << "b= " << it->Getb() << " c= " << it->Getc() << endl;
cout << "Index= " << idx << endl;
} else
cout << "CC is not found" << endl;
return 0;
}
find objects that have the same value for an attribute in a vector of objects
You would need to define a custom operator==
to loop over Pins
and pinNumNameMap (incidentally, I just answered another question about comparing custom objects in a vector here).
Here is what I came up with, although it might not be exactly what you need depending on whether you need all the entries in Pins
and pinNumNameMap
to match exactly or if comparing the size of the containers is enough.
EDIT: I merged the two sections into one to illustrate the possible use.
#include <iostream>
#include <string>
#include <vector>
#include <map>
#include <list>
#include <functional>
struct myObject
{
int numberOfSymbols;
std::list<int> symbolNumbers;
std::list<int> Pins;
std::list<std::string> pinNumList;
std::map<std::string, std::string> pinNumNameMap;
friend bool operator == (const myObject& _this, const myObject& _other)
{
// Check if entry sizes match
if (_this.Pins.size() != _other.Pins.size() ||
_this.pinNumNameMap.size() != _this.pinNumNameMap.size())
{
return false;
}
// Now check if the things inside the entries also match
bool same(true);
for (auto this_it = _this.Pins.begin(), other_it = _other.Pins.begin(); this_it != _this.Pins.end(); ++this_it, ++other_it)
{
same &= (*this_it == *other_it);
}
for (const auto& name : _this.pinNumNameMap)
{
same &= (_other.pinNumNameMap.find(name.first) != _other.pinNumNameMap.end() &&
_other.pinNumNameMap.at(name.first) == name.second);
}
return same;
}
};
// std::reference_wrapper is used when you want to
// store references to objects in a container like
// std::vector (you can't store myObject&)
typedef std::reference_wrapper<myObject> ObjRef;
int main()
{
std::vector<myObject> m_myObject;
// This is your comparison object.
// Use this to identify objectsin the original
// container with matching Pins and pinNumNameMaps.
myObject tmp;
tmp.Pins = {1, 2, 3};
tmp.pinNumNameMap =
{
{"pin 1", "name 1"},
{"pin 2", "name 2"},
{"pin 3", "name 3"}
};
std::vector<ObjRef> objectsWithCertainPins;
for (auto& obj : m_myObject)
{
if (obj == tmp)
{
// Use std::reference_wrapper to avoid
// copying large myObject instances
objectsWithCertainPins.emplace_back(std::ref(obj));
}
}
// Now you can iterate over objects in your
// objectsWithCertainPins container.
for (auto& obj : objectsWithCertainPins)
{
std::cout << "Pins:";
for (const auto& p : obj.get().Pins)
{
std::cout << " " << p;
}
std::cout << "\n";
}
return 0;
}
Iterate through a vector of objects and find a variable that matches one pulled from a text file
How do I compare the attribute from the file to the object using an
iterator?
Short answer: Suppose you have an iterator std::vector<Module*>::iterator iter
you can access the public members of Module
class like:
(*iter)->/*public member*/;
Long answer: First of all, you need a getter for private member id
and one setter for exMark
, by which you can get the id
of each Module
and compare to the id from the file and then set its exMark
to some value.
std::string getId()const { return code; }
void setExMark(const double newMark) { exMark = newMark; }
If you want to change the first true instance of Module
, you can use std::find_if
for finding the Module
:
std::string idFromFile = "two";
auto Condition = [&idFromFile](Module* element){ return element->getId() == idFromFile; };
auto iter = std::find_if(moduleVector.begin(), moduleVector.end(), Condition);
if(iter != moduleVector.end())
(*iter)->setExMark(10.0); // see this
// ^^^^^^^^^
See a sample code here
For multiple instances you can do:
for(auto iter = moduleVector.begin(); iter != moduleVector.end(); ++iter)
if ( (*iter)->getId() == idFromFile)
(*iter)->setExMark(10.0);
Note: In modern C++ you can use smart pointers, instead of raw pointers, which will delete the objects automatically as it goes out of scope.
Binary search on vector objects of an element greater than an attribute
For std::binary_search
to succeed, the range need to be sorted.std::binary_search
, std::lower_bound
works on sorted containers. So every time you add a new element into your vector
you need to keep it sorted.
For this purpose you can use std::lower_bound
in your insertion:
class X;
class XCompare
{
public:
bool operator()(const X& first, const X& second) const
{
// your sorting logic
}
};
X value(...);
auto where = std::lower_bound(std::begin(vector), std::end(vector), value, XCompare());
vector.insert(where, value);
And again you can use std::lower_bound
to search in your vector:
auto where = std::lower_bound(std::begin(vector), std::end(vector), searching_value, XCompare());
Don't forget to check if std::lower_bound
was successful:
bool successed = where != std::end(vector) && !(XCompare()(value, *where));
Or directly use std::binary_search
if you only want to know that element is in vector.
Sort a vector of objects by an object's attribute
You should implement an operator<
on cat so that cats can be sorted:
class cat {
public:
int age;
bool operator< (const cat &other) const {
return age < other.age;
}
};
You can then include the "algorithm" header and use std::sort
on your array:
vector< cat > catSorter::SortCatsByAge(){
vector< cat > cats_copy = cats;
std::sort(cats_copy.begin(), cats_copy.end());
return cats_copy;
}
Related Topics
In What Ways Do C++ Exceptions Slow Down Code When There Are No Exceptions Thown
Class Variables: Public Access Read-Only, But Private Access Read/Write
How to Generate a Random Double Uniformly Distributed Between 0 and 1 from C++
C++ Correct Way to Return Pointer to Array from Function
Catching Exceptions from a Constructor's Initializer List
How to Initialise a Dynamic Array in C++
What Do C and Assembler Actually Compile To
M_Pi Works with Math.H But Not with Cmath in Visual Studio
How to Scale Down Numbers from Rand()
What Happens to Global Variables Declared in a Dll
How to Create a Pause/Wait Function Using Qt
How to Catch Python Stdout in C++ Code
How to Initialize a Static Const Member in C++
Waitpid Equivalent with Timeout
Blending Does Not Remove Seams in Opencv
Can a Bool Read/Write Operation Be Not Atomic on X86
Is a Return Statement Mandatory for C++ Functions That Do Not Return Void