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;

      

+3


source to share


1 answer


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()

.

+1


source







All Articles