Sorting an array by multiple factors

Hello, I was trying to see if anyone can take a look at my code(I apologize in advanced if my title is misleading in any way - been a very long night). I am trying to have the output show the countries sorted by population and population density. I currently am able to sort by country name, this works just fine. I had some help elsewhere before, but now I am stuck again:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
#include <iostream>
#include <iomanip>
#include <cstring>
#include <cstdlib>

using namespace std;

class Country
{
public:
    Country();
    // Parameterized constructor
    Country(char name[], int population, int area);
    // setters and getters
    char* getName();
    int getPopulation();
    int getArea();
    void setName(char name[]);
    void setPopulation(int population);
    void setArea(int area);
private:
    // Declaring variables
    // Declaring instance variables
    char name[30];
    int population;
    int area;

};
Country::Country()
{

}

// Parameterized constructor
Country::Country(char n[], int population, int area)
{
    strcpy_s(name, n);
    this->population = population;
    this->area = area;
}
// setters and getters
char* Country::getName()
{
    return name;
}
int Country::getPopulation()
{
    return population;
}
int Country::getArea()
{
    return area;
}
void Country::setName(char n[])
{
    strcpy_s(name, n);
}
void Country::setPopulation(int population)
{
    this->population = population;
}
void Country::setArea(int area)
{
    this->area = area;
}


void sortByPopulation(Country counrties[], int SIZE);
void sortByPopulationDensity(Country counrties[], int SIZE);
void sortByName(Country counrties[], int SIZE);
void display(Country countries[], int SIZE);

int main() {
    //Declaring variables
    const int SIZE = 5;
    char name1[30] = { "England" };
    char name2[30] = { "Scotland" };
    char name3[30] = { "Ireland" };
    char name4[30] = { "Portugal" };
    char name5[30] = { "Belgium" };


    Country countries[SIZE];
    Country c1(name1, 55980000, 275);
    Country c2(name2, 5454000, 65);
    Country c3(name3, 4904000, 186);
    Country c4(name4, 10280000, 289);
    Country c5(name5, 11460000, 991);

    countries[0] = c5;
    countries[1] = c3;
    countries[2] = c4;
    countries[3] = c1;
    countries[4] = c2;

    sortByPopulation(countries, SIZE);
    cout << "_____________ After Sorting by Population _____________" << endl;
    display(countries, SIZE);

    sortByPopulationDensity(countries, SIZE);
    cout << "_____________ After Sorting by Population Density _____________" << endl;
    display(countries, SIZE);

    sortByName(countries, SIZE);
    cout << "_____________ After Sorting by name _____________" << endl;
    display(countries, SIZE);

    return 0;
}

void sortByPopulation(Country array[], int SIZE)
{
    //This Logic will Sort the Array of elements in Ascending order
    Country temp;
    for (int i = 0; i < SIZE; i++)
    {
        for (int j = i + 1; j < SIZE; j++)
        {
            if (array[i].getPopulation() > array[j].getPopulation())
            {
                temp = array[i];
                array[i] = array[j];
                array[j] = temp;
            }
        }
    }
}
void sortByPopulationDensity(Country array[], int SIZE)
{
    //This Logic will Sort the Array of elements in Ascending order
    Country temp;
    for (int i = 0; i < SIZE; i++)
    {
        for (int j = i + 1; j < SIZE; j++)
        {
            if ((array[i].getPopulation() / array[i].getArea()) > (array[j].getPopulation() / array[i].getArea()))
            {
                temp = array[i];
                array[i] = array[j];
                array[j] = temp;
            }
        }
    }
}
void sortByName(Country array[], int SIZE)
{
    //This Logic will Sort the Array of elements in Ascending order
    Country temp;
    for (int i = 0; i < SIZE; i++)
    {
        for (int j = i + 1; j < SIZE; j++)
        {
            if (strcmp(array[i].getName(), array[j].getName()) > 0)
            {
                temp = array[i];
                array[i] = array[j];
                array[j] = temp;
            }
        }
    }
}
void display(Country countries[], int SIZE)
{
    cout << setw(15) << left << "Name" << setw(15) << left << "Population " << setw(10) << left << "Area" << endl;
    cout << setw(15) << left << "----" << setw(15) << left << "---------- " << setw(10) << left << "----" << endl;

    for (int i = 0; i < SIZE; i++)
    {
        cout << setw(15) << left << countries[i].getName() << setw(15) << left << countries[i].getPopulation() << setw(10) << left << countries[i].getArea() << endl;
    }
}


Appreciate anyone who has any input.
Last edited on
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
#include <algorithm>
#include <iostream>
#include <iomanip>
#include <string>
#include <vector>

struct country
{
  std::string name;
  int population;
  int area;
};

double population_density(country c) { return static_cast<double>(c.population) / c.area; }

void display(std::vector<country> const& cs)
{
  auto const& field_width = std::setw(20);
  std::cout << std::left;
  
  std::cout << field_width << "Name" << field_width << "Population" << field_width << "Area" << '\n';
      
  for (country const& c: cs)
    std::cout << field_width << c.name << field_width << c.population << field_width << c.area << '\n';
}

int main()
{
  std::vector<country> countries
  { {"England",  55980000, 275}, {"Scotland", 5454000,  65 },
    {"Ireland",  4904000,  186}, {"Portugal", 10280000, 289},
    {"Belgium",  11460000, 991} };

  std::cout << "_____________ After Sorting by Population _____________\n";
  std::sort(countries.begin(), countries.end(), [](country a, country b) { return a.population < b.population; });
  display(countries);

  std::cout << "_____________ After Sorting by Population Density _____________\n";
  std::sort(countries.begin(), countries.end(), [](country a, country b) { return population_density(a) < population_density(b); });
  display(countries);

  std::cout << "_____________ After Sorting by name _____________\n";
  std::sort(countries.begin(), countries.end(), [](country a, country b) { return a.name < b.name; });
  display(countries);
}
Please state what your actual problem is.

It appears to sort correctly by name and by population.

So look at the population density case: you write an i where there should be a j at the end of line 136.

Did you know that there are library routines for swap and sort?
sorted by population and population density

Do you mean, once sorted by population, the countries with the highest population density should come before?
Most you have is worthy of keeping except for some re-shuffling and taking advantage of repetitive behavior, hence methods/functions.

The easily found index i,j =blooper is easily fixed.

std::<strings> are better than C-style strings (like stayin away from using namespace std nemesis - yawn - where have I heard that before)

Good on you for not taking the easy way out despite the <vector> patrol inspectors

getDensity() is a worthwhile method to simplify and add readability.

Your dataset, however genuine it is, should enable checking against what you are getting what you want. Fudge the data to enable testing, so that real data processing reliability can be demonstrated.

The sort by a plus b seems to be handled by the sequence sorting, mainly because the array changes to meet the immediate need. Maybe that's good, maybe not if you ever want to get back to the unsorted dataset.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
#include <iostream>
#include <iomanip>
#include <cstring>
#include <cstdlib>

using namespace std;

class Country
{
private:
    char name[30];
    int population;
    int area;
    
public:
    Country();
    Country(char* name, int population, int area);
    ~Country(){};
    
    char* getName();
    int getPopulation();
    int getArea();
    void setName(char name[]);
    void setPopulation(int population);
    void setArea(int area);
    void display();
    double getDensity();
    
    static void display_list(int SIZE, Country *countries)
    {
        for(int i = 0; i < SIZE; i++)
        countries[i].display();
    }
};

Country::Country(){}
Country::Country(char n[], int population, int area)
{
    strcpy(name, n);
    this->population = population;
    this->area = area;
}

char* Country::getName(){return name;}
int Country::getPopulation(){return population; }
int Country::getArea(){ return area;}
void Country::setName(char n[]){strcpy(name, n);}
void Country::setPopulation(int population){this->population = population;}
void Country::setArea(int area){this->area = area;}
double Country::getDensity(){return population/area;}

void Country::display()
{
    cout
    << setw(15) << left << name
    << setw(15) << left << population
    << setw(10) << left << area
    << setw(10) << left << getDensity()
    << '\n';
}

void sortByPopulation(Country counrties[], int SIZE);
void sortByPopulationDensity(Country counrties[], int SIZE);
void sortByName(Country counrties[], int SIZE);

int main()
{
    const int SIZE = 7;
    Country countries[SIZE];
    countries[0] = Country{"England" , 55980000, 275};
    countries[1] = Country{"Scotland", 5454000, 65};
    countries[2] = Country{"Ireland" , 4904000, 186};
    countries[3] = Country{"Portugal", 10280000, 289};
    countries[4] = Country{"Panama" , 11460000, 288};
    countries[5] = Country{"Angola" , 20000000, 991};
    countries[6] = Country{"Australia" , 20000000, 992};
    
    cout << "UNSORTED\n";
    Country::display_list(SIZE, countries);
    cout << "\n\n";
    
    sortByPopulation(countries, SIZE);
    cout << "SORTED BY POPULATION (ASC)\n";
    Country::display_list(SIZE, countries);
    cout << "\n\n";
    
    sortByPopulationDensity(countries, SIZE);
    cout << "--SORTED BY POPULATION DENSITY (ASC)\n";
    Country::display_list(SIZE, countries);
    cout << "\n\n";
    
    sortByName(countries, SIZE);
    cout << "SORTED BY NAME (ASC)\n";
    Country::display_list(SIZE, countries);
    cout << "\n\n";
    
    sortByName(countries, SIZE);
    sortByPopulationDensity(countries, SIZE);
    cout << "SORTED BY NAME THEN DENSITY (ASC)\n";
    Country::display_list(SIZE, countries);
    cout << "\n\n";
    
    sortByPopulationDensity(countries, SIZE);
    sortByName(countries, SIZE);
    cout << "SORTED BY DENSITY THEN NAME (ASC)\n";
    Country::display_list(SIZE, countries);
    cout << "\n\n";
    
    return 0;
}

void sortByPopulation(Country array[], int SIZE)
{
    // This Logic will Sort the Array of elements in Ascending order
    Country temp;
    for (int i = 0; i < SIZE; i++)
    {
        for (int j = i + 1; j < SIZE; j++)
        {
            if (array[i].getPopulation() > array[j].getPopulation())
            {
                temp = array[i];
                array[i] = array[j];
                array[j] = temp;
            }
        }
    }
}
void sortByPopulationDensity(Country array[], int SIZE)
{
    // This Logic will Sort the Array of elements in Ascending order
    Country temp;
    for (int i = 0; i < SIZE; i++)
    {
        for (int j = i + 1; j < SIZE; j++)
        {
            if ( array[i].getDensity() > array[j].getDensity() ) // <--
            {
                temp = array[i];
                array[i] = array[j];
                array[j] = temp;
            }
        }
    }
}

void sortByName(Country array[], int SIZE)
{
    // This Logic will Sort the Array of elements in Ascending order
    Country temp;
    for (int i = 0; i < SIZE; i++)
    {
        for (int j = i + 1; j < SIZE; j++)
        {
            if (strcmp(array[i].getName(), array[j].getName()) > 0)
            {
                temp = array[i];
                array[i] = array[j];
                array[j] = temp;
            }
        }
    }
}



UNSORTED
England        55980000       275       203563    
Scotland       5454000        65        83907     
Ireland        4904000        186       26365     
Portugal       10280000       289       35570     
Panama         11460000       288       39791     
Angola         20000000       991       20181     
Australia      20000000       992       20161     


SORTED BY POPULATION (ASC)
Ireland        4904000        186       26365     
Scotland       5454000        65        83907     
Portugal       10280000       289       35570     
Panama         11460000       288       39791     
Angola         20000000       991       20181     
Australia      20000000       992       20161     
England        55980000       275       203563    


--SORTED BY POPULATION DENSITY (ASC)
Australia      20000000       992       20161     
Angola         20000000       991       20181     
Ireland        4904000        186       26365     
Portugal       10280000       289       35570     
Panama         11460000       288       39791     
Scotland       5454000        65        83907     
England        55980000       275       203563    


SORTED BY NAME (ASC)
Angola         20000000       991       20181     
Australia      20000000       992       20161     
England        55980000       275       203563    
Ireland        4904000        186       26365     
Panama         11460000       288       39791     
Portugal       10280000       289       35570     
Scotland       5454000        65        83907     


SORTED BY NAME THEN DENSITY (ASC)
Australia      20000000       992       20161     
Angola         20000000       991       20181     
Ireland        4904000        186       26365     
Portugal       10280000       289       35570     
Panama         11460000       288       39791     
Scotland       5454000        65        83907     
England        55980000       275       203563    


SORTED BY DENSITY THEN NAME (ASC)
Angola         20000000       991       20181     
Australia      20000000       992       20161     
England        55980000       275       203563    
Ireland        4904000        186       26365     
Panama         11460000       288       39791     
Portugal       10280000       289       35570     
Scotland       5454000        65        83907     


Program ended with exit code: 0
Last edited on
@mbozzi this looks great and rather easier to read/comprehend! I ran your version and it did not sort by population density. I'm going to take a look to see if I can make an adjustment for it to sort by density. I appreciate the response.

@lastchance my code was not outputting a proper sort by population. My issue is the way my code outputs the proper sorting for countries by population and by population density. It outputs by name correctly. I only started C++ a month ago and have much to learn, I will have to look into and learn about library routines for swapping. Thank you for your input.

@enoizat correct, sorry for the vague question. the code properly creates a table for each; population, population density, and country name. The problem is, it would only sort by country name (A-Z) in all 3 tables and not population or population density.

@againtry I appreciate the coding compliment! Fairly new still and learning every day. I appreciate all these tips as well
@shawnphi,
I think you will find that @mbozzi's code IS correctly sorting by population density ... it's just that you aren't outputting that quantity to check.

As far as I can see, the only point where your code gives you the wrong answer is using an i when it should have been a j, and you have an integer division problem as well (note how @mbozzi casts to avoid this).

Your sorting technique does use an awful lot of swaps. You are also writing almost exactly the same code three times, which should send out a red flag.

If you didn't use strcpy_s, which is non-standard, we would be able to run your code in cpp.sh, the online compiler.
Last edited on
@lastchance ahh I see what you're saying. let me circle back to my original one and take a look at "i" and "j".
Last edited on
It doesn't affect the order here, but be careful about the integer division (and hence truncation) in calculating population density.
@shawnphi
I flagged the i,j problem in my post. It is in my line 137 which is your otherwise unchanged code for that function.

Keep in mind also that you could cut out at least one of the sorting functions and just have one for strings and one for numbers.

You can even reduce that to one only templated function if you’re up to that.

swapping 2 array elements can be a useful function simplification too. Keeps it simple, aids readability and assists de-bugging


Topic archived. No new replies allowed.