Creating a list of unique object pairs
I have a QVector of object instances Atom
, where each instance Atom
contains many Cartesian coordinates and a unique index ID, among other attributes. I have also defined a container Dyad
that is just a tuple of two instances Atom
. Basically, if my two instances Atom
satisfy the distance constraint, I want to be able to construct QList Dyad
s.
Let's say I had a Dyad
( Atom1
, Atom2
), how could I make sure my QList doesn't already contain a Dyad ( Atom2
, Atom1
)?
I have already tried using the QList function .contains()
and overloaded my operator ==
, but I cannot get it to work. I can attach the code I tried if I try to use the function contains()
, if it helps.
// Function definition
QList<AtomDyad> getUniqueAtomPairs(QVector<Atom> atomVector) {
QList<AtomDyad> AtomDyadPairList;
for (int iatom = 0; iatom < atomVector.size(); iatom++) {
for (int jatom = 0; jatom < atomVector.size(); jatom++) {
if (iatom == jatom) { continue; }
float x1 = atomVector[jatom].getX();
float x2 = atomVector[iatom].getX();
float y1 = atomVector[jatom].getY();
float y2 = atomVector[iatom].getY();
float z1 = atomVector[jatom].getZ();
float z2 = atomVector[iatom].getZ();
float Radii_Sum1 = atomVector[jatom].getvdW_radius(atomVector[jatom]) + atomVector[iatom].getvdW_radius(atomVector[iatom]);
if (DistanceBetween3DPoints(x1, x2, y1, y2, z1, z2) <= Radii_Sum1) {
AtomDyad MyDyad(atomVector[iatom], atomVector[jatom]);
// How can I ensure that MyDyad(atomVector[jatom], atomVector[iatom]) does not already exist?
AtomDyadPairList.append(MyDyad);
}
}
}
return AtomDyadPairList;
source to share
I'm not sure I know exactly what your Atom
and classes look like AtomDyad
, but I'll simulate them with a simple example to help you get the idea. I assume it Atom
has three coordinates: x, y and z. Now let the code:
struct Atom
{
Atom(float x, float y, float z)
: m_x(x), m_y(y), m_z(z)
{}
float m_x;
float m_y;
float m_z;
// Sort first by x, than by y and finally by z coordinates.
bool operator<(const Atom &other) const
{
if (m_x < other.m_x)
{
return true;
}
else if (m_x == other.m_x)
{
if (m_y < other.m_y)
{
return true;
}
else if (m_y == other.m_y)
{
if (m_z < other.m_z)
{
return true;
}
}
}
return false;
}
// To compare two atoms.
bool operator==(const Atom &other) const
{
return m_x == other.m_x && m_y == other.m_y && m_z == other.m_z;
}
};
Now, let's define a class AtomeDyad
that consists of two Atoms
:
struct AtomDyad
{
AtomDyad(const Atom &a1, const Atom &a2)
: m_a1(a1), m_a2(a2)
{}
Atom m_a1;
Atom m_a2;
bool operator<(const AtomDyad &other) const
{
if (m_a1 == other.m_a2 && m_a2 == other.m_a1)
{
return false;
}
if (m_a1 < other.m_a1)
{
return true;
}
else if (m_a1 == other.m_a1)
{
if (m_a2 < other.m_a2)
{
return true;
}
}
return false;
}
};
Finally, let it keep unique AtomDyads
. A unit test:
std::set<AtomDyad> uniqueAtomDyad;
Atom a1(0, 0, 0);
Atom a2(0, 0, 1);
Atom a3(0, 1, 1);
Atom a4(1, 1, 1);
AtomDyad ad1(a1, a2);
AtomDyad ad2(a3, a4);
AtomDyad ad3(a1, a2); // same as ad1
AtomDyad ad4(a4, a3); // swapped ad3
AtomDyad ad5(a1, a1);
AtomDyad ad6(a1, a1);
uniqueAtomDyad.insert(ad1);
uniqueAtomDyad.insert(ad2);
uniqueAtomDyad.insert(ad3); // not unique
uniqueAtomDyad.insert(ad4); // not unique
uniqueAtomDyad.insert(ad5);
uniqueAtomDyad.insert(ad6); // not unique
assert(uniqueAtomDyad.size() == 3);
You can check if an item has been added to the set by checking the return value of the function std::set::insert()
.
source to share