473,396 Members | 1,884 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,396 software developers and data experts.

Sorting data and creating multiple instances of the same class.

Daz
Hello people!

(This post is best viewed using a monospace font).

I need to create a class, which holds 4 elements:
std::string ItemName
int Calories
int Weight
int Density

I need to be able to create about 70 instances of this class, each with
different properties, then I need to sort them three times:
First, by calories. Then do some stuff.
Then by Weight. Then do more stuff.
And finally by Density. After which, I do more stuff.

It was suggested to me yesterday that I should use std::map in order to
sort the data, but I can't see how it would work. For example:
C W D <--(Pure coincidence)
"Fries"------10---159--45-
"Berry"------50---99---65-
"Ice Cream"--90---45---87-
"Hamburger"--4----76---23-

If sorted by Weight (W) should yield:

C W D

"Ice Cream"--90---45---87-
"Berry"------50---99---65-
"Hamburger"--4----76---23-
"Fries"------10---159--45-

I need to sort it by Density and Calories at some point too, yet the
rows need to stay intact.

No, my program isn't really _that_ lame, but that is the one of it's
simplest functions.

If I really can use a std::map, How would I go about doing it? I know I
am missing something really obvious here, but I have spent more hours
than anyone should pondering over this seemingly simple question, and
have not stumbled across any answers.

My next question, is:
Is there any easy way to create 70 instances of my class dynamically,
and iterate through them?

By this I mean, do I have to do:

BBObject Obj1("Berry",50,99,65);
BBObject Obj2("Fries",10,159,45);
BBObject Obj3("Hamburger",4,76,23);

....For 70 objects?

If so, then fair enough. However, if I can do this in a better way, and
somehow make a list so that I can iterate through the object, it would
be fantastic.
The only catch is, that the list order will need to change as I do the
sorting.

N.B. I do not want the code created for me. I am desparately trying to
learn what I can and can't do, along with how to do it. Just when I
think I understand a concept, I am always proved wrong by my own code.
If anyone can offer any advice on the best way to get the results I
need, I would very much appreciate it. Also, if anyone can straighten
me out abut anything I am trying to do which cannot be done, I would
also appreciate it.

Thanks everyone.

Daz

Jul 3 '06 #1
9 2812
Daz

Daz wrote:
If sorted by Weight (W) should yield:

C W D

"Ice Cream"--90---45---87-
Correction:

If sorted by Weight (W) should yield:

C W D

"Ice Cream"--90---45---87-
"Hamburger"--4----76---23-
"Berry"------50---99---65-
"Fries"------10---159--45-

Jul 3 '06 #2
Daz wrote:
Hello people!

(This post is best viewed using a monospace font).

I need to create a class, which holds 4 elements:
std::string ItemName
int Calories
int Weight
int Density

I need to be able to create about 70 instances of this class, each with
different properties, then I need to sort them three times:
First, by calories. Then do some stuff.
Then by Weight. Then do more stuff.
And finally by Density. After which, I do more stuff.

It was suggested to me yesterday that I should use std::map in order to
sort the data, but I can't see how it would work.
std::map is mostly useful if you have to sort by only one item. For your
case, I'd suggest std::vector in combination with std::sort and one
comparison function object for each element you want to sort by.
For example:
C W D <--(Pure coincidence)
"Fries"------10---159--45-
"Berry"------50---99---65-
"Ice Cream"--90---45---87-
"Hamburger"--4----76---23-

If sorted by Weight (W) should yield:

C W D

"Ice Cream"--90---45---87-
"Berry"------50---99---65-
"Hamburger"--4----76---23-
"Fries"------10---159--45-

I need to sort it by Density and Calories at some point too, yet the
rows need to stay intact.

No, my program isn't really _that_ lame, but that is the one of it's
simplest functions.

If I really can use a std::map, How would I go about doing it? I know I
am missing something really obvious here, but I have spent more hours
than anyone should pondering over this seemingly simple question, and
have not stumbled across any answers.

My next question, is:
Is there any easy way to create 70 instances of my class dynamically,
and iterate through them?

By this I mean, do I have to do:

BBObject Obj1("Berry",50,99,65);
BBObject Obj2("Fries",10,159,45);
BBObject Obj3("Hamburger",4,76,23);

...For 70 objects?
Again, use std::vector, like:

std::vector<BBOjectobjects;
objects.push_back(BBObject("Berry",50,99,65));
objects.push_back(BBObject("Fries",10,159,45));
objects.push_back(BBObject("Hamburger",4,76,23));
If so, then fair enough. However, if I can do this in a better way, and
somehow make a list so that I can iterate through the object, it would
be fantastic.
You can iterate through the vector with something like:

typedef std::vecctor<BBOject>::iterator iterator;

for (iterator it = objects.begin(), end = objects.end(); it != end; ++it)
{
std::cout << *it.ItemName;
}
The only catch is, that the list order will need to change as I do the
sorting.
Look for the std::sort function template, and especially for its third
argument. It can be used to specify a comparison function that will be used
as basis for the sorting.
N.B. I do not want the code created for me. I am desparately trying to
learn what I can and can't do, along with how to do it.
That's good. I hope I gave you neither too much nor too few information.

Jul 3 '06 #3
Daz

Rolf Magnus wrote:
Daz wrote:
Hello people!

(This post is best viewed using a monospace font).

I need to create a class, which holds 4 elements:
std::string ItemName
int Calories
int Weight
int Density

I need to be able to create about 70 instances of this class, each with
different properties, then I need to sort them three times:
First, by calories. Then do some stuff.
Then by Weight. Then do more stuff.
And finally by Density. After which, I do more stuff.

It was suggested to me yesterday that I should use std::map in order to
sort the data, but I can't see how it would work.

std::map is mostly useful if you have to sort by only one item. For your
case, I'd suggest std::vector in combination with std::sort and one
comparison function object for each element you want to sort by.
For example:
C W D <--(Pure coincidence)
"Fries"------10---159--45-
"Berry"------50---99---65-
"Ice Cream"--90---45---87-
"Hamburger"--4----76---23-

If sorted by Weight (W) should yield:

C W D

"Ice Cream"--90---45---87-
"Berry"------50---99---65-
"Hamburger"--4----76---23-
"Fries"------10---159--45-

I need to sort it by Density and Calories at some point too, yet the
rows need to stay intact.

No, my program isn't really _that_ lame, but that is the one of it's
simplest functions.

If I really can use a std::map, How would I go about doing it? I know I
am missing something really obvious here, but I have spent more hours
than anyone should pondering over this seemingly simple question, and
have not stumbled across any answers.

My next question, is:
Is there any easy way to create 70 instances of my class dynamically,
and iterate through them?

By this I mean, do I have to do:

BBObject Obj1("Berry",50,99,65);
BBObject Obj2("Fries",10,159,45);
BBObject Obj3("Hamburger",4,76,23);

...For 70 objects?

Again, use std::vector, like:

std::vector<BBOjectobjects;
objects.push_back(BBObject("Berry",50,99,65));
objects.push_back(BBObject("Fries",10,159,45));
objects.push_back(BBObject("Hamburger",4,76,23));
If so, then fair enough. However, if I can do this in a better way, and
somehow make a list so that I can iterate through the object, it would
be fantastic.

You can iterate through the vector with something like:

typedef std::vecctor<BBOject>::iterator iterator;

for (iterator it = objects.begin(), end = objects.end(); it != end; ++it)
{
std::cout << *it.ItemName;
}
The only catch is, that the list order will need to change as I do the
sorting.

Look for the std::sort function template, and especially for its third
argument. It can be used to specify a comparison function that will be used
as basis for the sorting.
N.B. I do not want the code created for me. I am desparately trying to
learn what I can and can't do, along with how to do it.

That's good. I hope I gave you neither too much nor too few information.
That's fantastic! Thanks for your help Rolf. You're a diamond!

Jul 3 '06 #4
Daz

Daz wrote:
That's fantastic! Thanks for your help Rolf. You're a diamond!
Hello again.

I can't seem to get sort to work. I know I am missing something, and
probably not using the template properly, but I don't understand how. I
have tried at least 30 different things, and each time I just get more
errors.

The code below gives a single error:

void InitializeBBObjects()
{
std::vector<BBObjectobjects;
typedef std::vector<BBObject>::iterator iterator;
iterator it = objects.begin(), end = objects.end();

objects.push_back(BBObject(BERRY,50,99,65,"Berry") );
objects.push_back(BBObject(FOOD,10,159,45,"Fries") );
objects.push_back(BBObject(FOOD,4,76,23,"Hamburger "));

std::sort<iterator>(*it, *end); // <-- This is whre the error lies.
}

The above is basically a simple test script to help me try to figure
out how to do a sort. I have used sort before on a list of ints, but I
don't have any idea what I need to change in order to make it work with
a list of my objects.

Any more input would be appreciated (sorry Rolf) :(

Best wishes.

Daz

Jul 3 '06 #5
Daz wrote:
>
Daz wrote:
>That's fantastic! Thanks for your help Rolf. You're a diamond!

Hello again.

I can't seem to get sort to work. I know I am missing something, and
probably not using the template properly, but I don't understand how. I
have tried at least 30 different things, and each time I just get more
errors.

The code below gives a single error:

void InitializeBBObjects()
{
std::vector<BBObjectobjects;
typedef std::vector<BBObject>::iterator iterator;
iterator it = objects.begin(), end = objects.end();

objects.push_back(BBObject(BERRY,50,99,65,"Berry") );
objects.push_back(BBObject(FOOD,10,159,45,"Fries") );
objects.push_back(BBObject(FOOD,4,76,23,"Hamburger "));
Not a good idea. Adding objects to your vector invalidates all iterators
into that vector, so you should create the iterators after your push_back.
std::sort<iterator>(*it, *end); // <-- This is whre the error lies.
std::sort wants iterators, not the objects they point to, so don't use the
dereference operator. Just use:

std::sort(it, end);

or directly:

std::sort(objects.begin(), objects.end());

However, it still won't work that way, because sort needs a way to compare
two objects, and by default it uses operator< for that, which isn't defined
for your objects. Since you want to sort by different elements, you need to
write your own comparison function that compares two objects by the member
you want to sort by.
}

The above is basically a simple test script to help me try to figure
out how to do a sort. I have used sort before on a list of ints, but I
don't have any idea what I need to change in order to make it work with
a list of my objects.

Any more input would be appreciated (sorry Rolf) :(
You're welcome. A good book about C++ should explain that all. You should
consider getting one. IIRC, the FAQ to this newsgroup contains a list of
candidates.
Jul 3 '06 #6
Daz

Rolf Magnus wrote:
Daz wrote:

Daz wrote:
That's fantastic! Thanks for your help Rolf. You're a diamond!
Hello again.

I can't seem to get sort to work. I know I am missing something, and
probably not using the template properly, but I don't understand how. I
have tried at least 30 different things, and each time I just get more
errors.

The code below gives a single error:

void InitializeBBObjects()
{
std::vector<BBObjectobjects;
typedef std::vector<BBObject>::iterator iterator;
iterator it = objects.begin(), end = objects.end();

objects.push_back(BBObject(BERRY,50,99,65,"Berry") );
objects.push_back(BBObject(FOOD,10,159,45,"Fries") );
objects.push_back(BBObject(FOOD,4,76,23,"Hamburger "));

Not a good idea. Adding objects to your vector invalidates all iterators
into that vector, so you should create the iterators after your push_back.
std::sort<iterator>(*it, *end); // <-- This is whre the error lies.

std::sort wants iterators, not the objects they point to, so don't use the
dereference operator. Just use:

std::sort(it, end);

or directly:

std::sort(objects.begin(), objects.end());

However, it still won't work that way, because sort needs a way to compare
two objects, and by default it uses operator< for that, which isn't defined
for your objects. Since you want to sort by different elements, you need to
write your own comparison function that compares two objects by the member
you want to sort by.
}

The above is basically a simple test script to help me try to figure
out how to do a sort. I have used sort before on a list of ints, but I
don't have any idea what I need to change in order to make it work with
a list of my objects.

Any more input would be appreciated (sorry Rolf) :(

You're welcome. A good book about C++ should explain that all. You should
consider getting one. IIRC, the FAQ to this newsgroup contains a list of
candidates.
Mr. Burns mode - ON;
E-e-e-excellent!
Mr Burns mode - OFF;

Thanks again Rolf. It makes complete sense now and to tell the truth, I
already knew the answer, yet for some strange reason, I always seem to
forget the answer right when I most need to remember it.

Thanks for your patience and time. You really have helped me out a lot!

Jul 3 '06 #7
In article <11**********************@h44g2000cwa.googlegroups .com>,
cu********@gmail.com says...
Hello people!

(This post is best viewed using a monospace font).

I need to create a class, which holds 4 elements:
std::string ItemName
int Calories
int Weight
int Density

I need to be able to create about 70 instances of this class, each with
different properties, then I need to sort them three times:
First, by calories. Then do some stuff.
Then by Weight. Then do more stuff.
And finally by Density. After which, I do more stuff.
Just to clarify, I'm going to explicitly state a couple of
assumptions. First of all, it sounds like the data are basically
static -- i.e. you create all of them, and then after that you won't
add or delete any data; you just need to shuffle the existing data
into different arrangements.

Second, it sounds like you only need to work with one arrangement at
a time -- once you start working with the data in a different order,
you're done working with it in the previous order.

Assuming those are both correct, then a map is probably not your best
choice. You're almost certainly better off using an std::vector, and
then using std::sort to sort the data as needed.

To do that, you generally need to create some predicates (usually as
functors) to do the comparisons correctly:

struct Item {
std::string name;
int calories;
int weight;
int density;
};

struct by_calories {
bool operator<(Item const &a, Item const &b) {
return a.calories < b.calories;
}
};

struct by_weight {
bool operator<(Item const &a, Item const &b) {
return a.weight < b.weight;
}
};

Then you specify the appropriate comparison when you do your sort:

std:vector<Itemitems;

// Insert data into vector of items here.

std::sort(items.begin(), items.end(), by_calories());
// simulate processing by printing out:
std::copy(items.begin(), items.end(),
std::ostream_iterator<Item>(std::cout, "\n"));

// Now a different order:
std::sort(items.begin(), items.end(), by_weight());
// print out again.
std::copy(items.begin(), items.end(),
std::ostream_iterator<Item>(std::cout, "\n"));

Of course, for those 'copy' calls to work, you'd need to define an
operator<< for Item, so the ostream_iterator knows how to write each
item out. That'd typically be pretty simple, just writing out the
data in order, probably with tabs between them.

Now, let's consider what happens if those assumptions are wrong. If
your data is really dynamic, then you probably _do_ want to use
std::map or std::set after all. Since you apparently want to iterate
in a particular order, but don't need to do lookups based on a single
'key' part, you probably want a set instead of a map. In this case,
you'd (again) use comparison predicates like above, but you'd specify
the correct predicate as part of the type of the set:

std::set<Item, by_caloriesitems_c;
std::set<Item, by_weightitems_w;

Then you'd start by putting the data into items_c, then when you're
done working with it in order by calories, you copy the data to
items_w, so it'll be sorted by weight. After you're done with that
order, you copy it to a set ordered by density, and so on. In each
case, since it's in a set you can efficiently add and/or remove items
on the fly.

If the second assumption is incorrect, and you really want to be able
to access the data in any order at any time efficiently, you need to
maintain all the orders simultaneously. In this case, you'll probably
want to store the data in one place, and then create three separate
indices by which to access the data. In this case, you get a hybrid:
typically a vector to hold the data itself, and either vectors or
sets of pointers to the data (depending on whether you need to
add/delete data on the fly).

--
Later,
Jerry.

The universe is a figment of its own imagination.
Jul 3 '06 #8
Daz

Jerry Coffin wrote:
Just to clarify, I'm going to explicitly state a couple of
assumptions. First of all, it sounds like the data are basically
static -- i.e. you create all of them, and then after that you won't
add or delete any data; you just need to shuffle the existing data
into different arrangements.
Correct!
Second, it sounds like you only need to work with one arrangement at
a time -- once you start working with the data in a different order,
you're done working with it in the previous order.
Not necessarily true, but I do have this in mind for now, yes. Ya know,
you should do this program-mind-reading for a living. You really are
rather good at it.
Assuming those are both correct, then a map is probably not your best
choice. You're almost certainly better off using an std::vector, and
then using std::sort to sort the data as needed.
Amen to that! I love vectors, even though I know next to nothing about
them, they are just so robust and versatile.
To do that, you generally need to create some predicates (usually as
functors) to do the comparisons correctly:
Ok.
struct Item {
std::string name;
int calories;
int weight;
int density;
};
Right.
struct by_calories {
bool operator<(Item const &a, Item const &b) {
return a.calories < b.calories;
}
};
Uhuh.
struct by_weight {
bool operator<(Item const &a, Item const &b) {
return a.weight < b.weight;
}
};

Then you specify the appropriate comparison when you do your sort:
Aaaaah! <insert fiendish grin here>
std:vector<Itemitems;

// Insert data into vector of items here.

std::sort(items.begin(), items.end(), by_calories());
// simulate processing by printing out:
std::copy(items.begin(), items.end(),
std::ostream_iterator<Item>(std::cout, "\n"));

// Now a different order:
std::sort(items.begin(), items.end(), by_weight());
// print out again.
std::copy(items.begin(), items.end(),
std::ostream_iterator<Item>(std::cout, "\n"));
Ha! Fantastic! Ingenious! You make it look so easy. I have a nack for
making things more complicated than they might need to be...
Of course, for those 'copy' calls to work, you'd need to define an
operator<< for Item, so the ostream_iterator knows how to write each
item out. That'd typically be pretty simple, just writing out the
data in order, probably with tabs between them.
Sounds simple. However... Simple + me = complicated++
Now, let's consider what happens if those assumptions are wrong. If
your data is really dynamic, then you probably _do_ want to use
std::map or std::set after all. Since you apparently want to iterate
in a particular order, but don't need to do lookups based on a single
'key' part, you probably want a set instead of a map. In this case,
you'd (again) use comparison predicates like above, but you'd specify
the correct predicate as part of the type of the set:

std::set<Item, by_caloriesitems_c;
std::set<Item, by_weightitems_w;

Then you'd start by putting the data into items_c, then when you're
done working with it in order by calories, you copy the data to
items_w, so it'll be sorted by weight. After you're done with that
order, you copy it to a set ordered by density, and so on. In each
case, since it's in a set you can efficiently add and/or remove items
on the fly.

If the second assumption is incorrect, and you really want to be able
to access the data in any order at any time efficiently, you need to
maintain all the orders simultaneously. In this case, you'll probably
want to store the data in one place, and then create three separate
indices by which to access the data. In this case, you get a hybrid:
typically a vector to hold the data itself, and either vectors or
sets of pointers to the data (depending on whether you need to
add/delete data on the fly).
That's all good and useful, but you really were spot-on with your
assumptions. I am most impressed!

Sorry if any of that sounded sarcastic. I seriously am impressed and
overwhelmed at the help and support some people give, and can only hope
that I too will be able to help fellow coders so efficiently.
Naturally, this also applies to everyone else who has helped me in the
past, too.

I hope I can remember most of that. If I can it would be a great help.
I think I have a memory leak, and need to get around to deploying a
debugging script in my brain.

Many, many thanks to everyone again! :)

Jul 3 '06 #9
In article <11*********************@j8g2000cwa.googlegroups.c om>,
cu********@gmail.com says...

[ ... ]
Not necessarily true, but I do have this in mind for now, yes. Ya know,
you should do this program-mind-reading for a living. You really are
rather good at it.
That's called "defining requirements", or various other things on
that order -- it's probably the single most crucial part of
programming in general. It's how you minimize the standard "yes,
that's exactly what we asked for, but not at all what we want"
situation.

[ ... ]
Of course, for those 'copy' calls to work, you'd need to define an
operator<< for Item, so the ostream_iterator knows how to write each
item out. That'd typically be pretty simple, just writing out the
data in order, probably with tabs between them.

Sounds simple. However... Simple + me = complicated++
Oh, well, it'd typically look something like this:

std::ostream &operator<<(std::ostream &os, Item const &i) {
return os << i.name << "\t"
<< i.calories << "\t"
<< i.weight << "\t"
<< i.density;
}

--
Later,
Jerry.

The universe is a figment of its own imagination.
Jul 3 '06 #10

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

4
by: Altramagnus | last post by:
I have 30 - 40 type of different window. For each type I need about 20 instances of the window. When I try to create them, I get "Error creating window handle" My guess is there is a maximum...
4
by: suzy | last post by:
hello. how can i sort data in a dataset? all the examples i have seen on msdn, etc are sorting a dataview. this works fine, but i want to return the results in xml and the dataview doesn't...
8
by: Mike MacSween | last post by:
tblCourses one to many to tblEvents. A course may have an intro workshop (a type of event), a mid course workshop, a final exam. Or any combination. Or something different in the future. At...
0
by: Brian Henry | last post by:
Here is another virtual mode example for the .NET 2.0 framework while working with the list view. Since you can not access the items collection of the list view you need to do sorting another...
2
by: Rob Meade | last post by:
Dear all, I have a class which contains an arraylist populated with other objects, for example: PrescriptionQueue - containing multiple instances of Prescription I have the need on my web...
0
by: rbg | last post by:
Have a web application which uses Data Cache. I need to understand what happens when a new instance of the same web application is created for for serving concurrent clients. What happens when...
7
by: Kamal | last post by:
Hello all, I have a very simple html table with collapsible rows and sorting capabilities. The collapsible row is hidden with css rule (display:none). When one clicks in the left of the...
2
by: ChrisO | last post by:
I've been pretty infatuated with JSON for some time now since "discovering" it a while back. (It's been there all along in JavaScript, but it was just never "noticed" or used by most until...
6
by: =?Utf-8?B?RGFu?= | last post by:
I am reposting a question from about 3 weeks ago ("sorting capability"). I have an aspx page in which I get the data from a database dynamically, through C# code, by creating a dynamic table...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
0
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.