Lith
Lith

Reputation: 1325

Sort structure array in alphabetical order

I have a structure array (A[#]) named Sheep (since my task is about sheeps DNR). After I do whatever the task asked I am left with this struct :

struct Sheep 
{
    string Vardas;
    char Fragmentas[CMax]; 
    int atitikme = 0; 
};

and inside my it the data is:

(string Vardas) | (char Fragmentas[CMax]) | (int atitikme)
Baltukas   TAGCTT 3
Bailioji   ATGCAA 3 
Smarkuolis AATGAA 1 

(char Fragmentas[CMax] won't be using so u don't have to look at it, I only named it to make it clear).

ALL of this data comes from U2.txt file and cant be manually typed in a code.

All its left to do is to sort it by these rules:

  1. It goes from bigger to smaller by 'int atitikme'.
  2. IF 'int atitikme' is equal then it will have to sort by 'A[#].Vardas in a in alphabetical order.

To sort it by 'int atitikme' I created a code:

string q;
char w[20];
int e;
for (int o = 0; o < n-1; o++) 
{
    for (int p = o+1; p < n-1; p++) 
    {
        if (A[p].atitikme > A[o].atitikme) 
        {
            // - Vardo Keitimas
            q = A[o].Vardas;
            A[o].Vardas = A[p].Vardas;
            A[p].Vardas = q;
            // - A[#].atitikme keitimas
            e = A[o].atitikme;
            A[o].atitikme = A[p].atitikme;
            A[p].atitikme = e;
            // - DNR farkmentu keitimas
            for (int r = 0; r < m; r++) 
            {
                w[r] = A[o].Fragmentas[r];
                A[o].Fragmentas[r] = A[p].Fragmentas[r];
                A[p].Fragmentas[r] = w[r];
             }
        }
    }
}

n = 4 | m = 6

How/what do i need to add to this code to make it go:

else if (A[p].atitikme == A[o].atitikme) 
{
    <code>
}

That if 'atitikme' is == to another 'atitikme' then A[p].Vardas and A[o].Vardas has to be sorted in an alphabetical order. but only those 2 from the whole array.

OR if its too hard to understand what I meant, could anyone post a code, in the answer box, were it would sort in a alphabetical order between 2 string's?

NOTE: the whole line data

(string Vardas) (char Fragmentas[CMax]) (int atitikme)

has to stay the same, only the place in the line has to be diffirent and sorted by those rules I mentioned before.

The output should be:

Bailioji   3
Baltukas   3
Smarkuolis 1

EDIT: My current output is:

Baltukas   3
Bailioji   3
Smarkuolis 1

P.s. The task allows to use everything as-long as its C++ and does not have to create, or read, any other file.

Upvotes: 4

Views: 2154

Answers (3)

JeJo
JeJo

Reputation: 32797

Here I have used std::vector<> instead of array to store the sheeps. Secondly, using std::sort() and a lambda function, you can easily mention how you want to sort the elements in the std::vector<>/ Sheeps. That would be the easiest way to approach.

Here is the live code, in case of reviewing: https://www.ideone.com/ay7TWU

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

struct Sheep
{
   std::string Vardas;
   std::vector<char> Fragmentas;
   int atitikme;
};

int main()
{
  std::vector<Sheep> vec =
   {
      {"Baltukas",  {'T','A','G','C','T','T'}, 3},
      {"Bailioji",  {'A','T','G','C','A','A'}, 3},
      {"Smarkuolis",{'A','A','T','G','A','A'}, 1},
      {"Hmarkuolis",{'A','A','T','G','A','A'}, 1},
      {"Kmarkuolis",{'A','A','T','G','A','A'}, 2}
   };

   std::sort(vec.begin(), vec.end(), [](const Sheep& lhs, const Sheep& rhs)
      {
         return (lhs.atitikme == rhs.atitikme) ? 
            lhs.Vardas < rhs.Vardas: // if atitikme's of sheeps are equal
            lhs.atitikme > rhs.atitikme; // if atitikme's of sheeps are not equal
      });

    for (const auto& it: vec)
        std::cout << it.Vardas << " " << it.atitikme << "\n";

    return 0;
}

The output:

Bailioji 3
Baltukas 3
Kmarkuolis 2
Hmarkuolis 1
Smarkuolis 1

Upvotes: 5

Aziuth
Aziuth

Reputation: 3902

https://en.cppreference.com/w/cpp/algorithm/sort shows you how to use std::sort.

You write a function bool less_than(const Sheep& a, const Sheep& b) that represents the order of two sheep and then simply call std::sort(container.begin(), container.end(), less_than);, with container being something like a vector of Sheep.

Edit: The function written out:

bool less_than(const Sheep& a, const Sheep& b)
{
    if(a.atitikme != b.atitikme) return a.atitikme < b.atitikme;
    return a.Vardas < b.Vardas;
}

Upvotes: 1

PiotrNycz
PiotrNycz

Reputation: 24412

The best is to solve your problem one by one.

First - define the sorting order - see doc about - e.g. in std::less

So, you need functor class that defines your sorting order:

class SheepOrder
{
public:
    bool operator() ( const Sheep& left, const Sheep& right) const
    {
        // It goes from bigger to smaller by 'int atitikme'.
        if (left.atitikme > right.atitikme)
             return true;
        if (left.atitikme < right.atitikme)
             return false;

        //IF 'int atitikme' is equal then it will have to sort it in a in alphabetical order. 
        // I guess you meant Vardas
        return left.Vardas < right.Vardas;
    }
};

Now, having defined the order - just use std::sort - it can be used with arrays - no problem:

Sheep sheeps[100];
// .. 
std::sort(std::begin(sheeps), std::end(sheeps), SheepOrder{});

or:

void sortSheeps(Sheep* array, std::size_t numOFSheeps)
{
    std::sort(array, array + numOfSheeps, SheepOrder{});
}

You can also use std::tuple to make it easier to define sorting order (tuple has operator < by default if their elements have this operator too):

class SheepOrder
{
public:
    bool operator() ( const Sheep& left, const Sheep& right) const
    {
        return tieMembersForSorting(left) < tieMembersForSorting(right);
    }
private:
    static auto tieMembersForSorting( const Sheep& object)
    {
        return std::make_tuple(-object.atitikme, // - to revert order
                               std::ref(object.Vardas)); // ref - to not make copy of string
    } 
};

With tieMembersForSorting defined as free function - lambda could be used as well (as it will be just one liner):

    inline auto tieMembersForSorting( const Sheep& object)
    {
        return std::make_tuple(-object.atitikme, // - to revert order
                               std::ref(object.Vardas)); // ref - to not make copy of string
    } 

    std::sort(begin(...), end(...), [](Sheep const& left, Sheep const& right)
              { return tieMembersForSorting(left) < tieMembersForSorting(right); });                    

Upvotes: 2

Related Questions