473,402 Members | 2,053 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,402 software developers and data experts.

Sorting a list of objects

Hello,

I'm finishing a speech recognition jukebox
(http://intelligentjukebox.com/) I have a very basic template
question. I can't find any good examples of what I want to do. I
could write my own sort function faster than I could find a good
reference with examples on the c++ template library.

Can someone tell me how to define the "<" operator so I can use the
sort function for the list template. I want to sort Song objects in
a-z (descending) order by m_filename.

thanks

Here is my code:
//------------------------------------------------------------------------------

class Song
{
public:
Album* m_pAlbum; // make it easy to get the album
string m_name; //display name
string m_filename;
};

list<Song*> *pSongsList; // holds all the songs for this album

//------------------------------------------------------------------------------

I want to this function call to work:

pSongsList->sort();

Aug 16 '05 #1
12 9884
Jeff wrote:
Hello,

I'm finishing a speech recognition jukebox
(http://intelligentjukebox.com/) I have a very basic template
question. I can't find any good examples of what I want to do. I
could write my own sort function faster than I could find a good
reference with examples on the c++ template library.

Can someone tell me how to define the "<" operator so I can use the
sort function for the list template. I want to sort Song objects in
a-z (descending) order by m_filename.

thanks

Here is my code:
//------------------------------------------------------------------------------

class Song
{
public:
Album* m_pAlbum; // make it easy to get the album
string m_name; //display name
string m_filename;
};

list<Song*> *pSongsList; // holds all the songs for this album

//------------------------------------------------------------------------------

I want to this function call to work:

pSongsList->sort();


You can't, because that function call would use operator< on the element
type, which is pointer to Song. You cannot change the built-in behavior of
pointers, therefore you cannot overload that operator<.
What you can do is specify an alternative comparison:

struct song_cmp
{
bool operator()(Song* lhs, Song* rhs) const
{
return lhs->m_filename < rhs->m_filename;
}
};

pSongList.sort(song_cmp());

Aug 16 '05 #2
On Wed, 17 Aug 2005 01:06:13 +0200, Rolf Magnus <ra******@t-online.de>
wrote:

You can't, because that function call would use operator< on the element
type, which is pointer to Song. You cannot change the built-in behavior of
pointers, therefore you cannot overload that operator<.
What you can do is specify an alternative comparison:

struct song_cmp
{
bool operator()(Song* lhs, Song* rhs) const
{
return lhs->m_filename < rhs->m_filename;
}
};

pSongList.sort(song_cmp());


I'm using VC++ 6.0. Can you tell me how to make this compile?
thanks
-------------------------------
line 95:
m_pSongsList->sort(song_cmp());
Compiling...
music.cpp
J:\home\jeff\src\intelligent_jukebox\dev\intellimu sic\current\music.cpp(95)
: error C2664: 'void __thiscall std::list<class Song *,class
std::allocator<class Song *> >::sort(struct std::greater<class Song
*>)' : cannot convert parameter 1 from 'stru
ct song_cmp' to 'struct std::greater<class Song *>'
No constructor could take the source type, or constructor
overload resolution was ambiguous
Aug 17 '05 #3
In five minutes I wrote a bubble sort which added less than 1/10 of a
second to the startup time of my program for 14,000 songs. Most
albums have less than 20 songs.

I spent more than two hours trying to figure out the retarded notation
to sort a list and failed. Apparently there are no clear examples of
how to sort a list using your own comparison function. Sometimes I
really hate c++.

thanks for the help anyway though

int n;
bool bSorted = false;
Song* tmpSong;

while (false == bSorted)
{
bSorted = true;
for (n = 0; n < m_totalSongs-1; n++)
{
if ( (m_pSongsArray[n])->m_filename >
(m_pSongsArray[n+1])->m_filename )
{
// swap values
tmpSong = m_pSongsArray[n];
m_pSongsArray[n] = m_pSongsArray[n+1];
m_pSongsArray[n+1] = tmpSong;
bSorted = false;
}
}
} // end while

Aug 17 '05 #4
The problem is std::sort requires random-access iterators, which
std::list lacks.

According to my copy of Plauger's _The C++ Standard Template Library_,
std::stable_sort should accept bidirectional iterators (see pg. 160).
According to Josuttis (pg. 397), std::stable_sort requires
random-access iterators. I don't know what the Standard itself says,
unfortunately.

Still, it may be worth trying std::stable_sort, to see if your system
supports it. G++ 4.0 doesn't.

Other options: copy the list into a vector and then sort it. Or write
your own out-of-place mergesort function, and do it the LISPy way.
Either way, you should be able to get roughly O(n lg n) performance
without too much headache. E.g.:

=====

int main()
{
int vals[] = { 2, 1, 5, 6, 4, 9, 8, 7, 3 };
list<int> l(vals, vals + 9);
vector<int> v(l.begin(), l.end());
sort(v.begin(), v.end());
l.assign(v.begin(), v.end());
copy(l.begin(), l.end(), ostream_iterator<int>(cout, "\t"));
cout << endl;
return 0;
}

=====

That doesn't seem to be too obnoxiously bad to me.

Aug 17 '05 #5
Jeff wrote:
On Wed, 17 Aug 2005 01:06:13 +0200, Rolf Magnus <ra******@t-online.de>
wrote:

You can't, because that function call would use operator< on the element
type, which is pointer to Song. You cannot change the built-in behavior of
pointers, therefore you cannot overload that operator<.
What you can do is specify an alternative comparison:

struct song_cmp
{
bool operator()(Song* lhs, Song* rhs) const
{
return lhs->m_filename < rhs->m_filename;
}
};

pSongList.sort(song_cmp());

I'm using VC++ 6.0. Can you tell me how to make this compile?
thanks


That's easy...NOT!
It's one of those M$-VC++ stupidities.
I solved it by a template spezialization for std::greater<Song*>
(Hint: Search for _Pr3 in include file 'list' to see what's going on
there...)

<code>

namespace std
{
template<>
struct greater<Song*>
{
bool operator()(const Song* lhs, const Song* rhs) const
{
return lhs->m_filename < rhs->m_filename;
}
};
}
....
....
pSongList->sort(std::greater<Song*>());

</code>

That works for me.

HTH

Stefan
Aug 17 '05 #6
ci********@gmail.com wrote:
The problem is std::sort requires random-access iterators, which
std::list lacks.

According to my copy of Plauger's _The C++ Standard Template Library_,
std::stable_sort should accept bidirectional iterators (see pg. 160).
According to Josuttis (pg. 397), std::stable_sort requires
random-access iterators. I don't know what the Standard itself says,
unfortunately.

Still, it may be worth trying std::stable_sort, to see if your system
supports it. G++ 4.0 doesn't.

Other options: copy the list into a vector and then sort it. Or write
your own out-of-place mergesort function, and do it the LISPy way.
Either way, you should be able to get roughly O(n lg n) performance
without too much headache. E.g.:

=====

int main()
{
int vals[] = { 2, 1, 5, 6, 4, 9, 8, 7, 3 };
list<int> l(vals, vals + 9);
vector<int> v(l.begin(), l.end());
sort(v.begin(), v.end());
l.assign(v.begin(), v.end());
copy(l.begin(), l.end(), ostream_iterator<int>(cout, "\t"));
cout << endl;
return 0;
}

=====

That doesn't seem to be too obnoxiously bad to me.


The drawback with using any of these suggestions to sort a std::list is
that iterators of the list may no longer point to the same values as
they did before the list was sorted.

For that reason std::list provides two sort() methods of its own, one
that sorts the list in an ascending order, and another that sorts it
using a user defined predicate for comparing elements. Clearly one of
these two std::list member functions is the preferred way to sort
elements in a std::list. Both of these methods guarantee not to have
changed any of the list's iterators once the list has been sorted.

Greg

Aug 17 '05 #7

Jeff wrote:
In five minutes I wrote a bubble sort which added less than 1/10 of a
second to the startup time of my program for 14,000 songs. Most
albums have less than 20 songs.

I spent more than two hours trying to figure out the retarded notation
to sort a list and failed. Apparently there are no clear examples of
how to sort a list using your own comparison function. Sometimes I
really hate c++.

thanks for the help anyway though

int n;
bool bSorted = false;
Song* tmpSong;

while (false == bSorted)
{
bSorted = true;
for (n = 0; n < m_totalSongs-1; n++)
{
if ( (m_pSongsArray[n])->m_filename >
(m_pSongsArray[n+1])->m_filename )
{
// swap values
tmpSong = m_pSongsArray[n];
m_pSongsArray[n] = m_pSongsArray[n+1];
m_pSongsArray[n+1] = tmpSong;
bSorted = false;
}
}
} // end while


Actually, to use list::sort you can just provide the name of a function
to perform the comparison:

bool CompareSongs( const Song * leftSong, const Song * rightSong)
{
return leftSong->m_filename < rightSong->m_filename;
}

int main()
{
...
pSongsList->sort( CompareSongs );
...
}

Greg

Aug 17 '05 #8
Greg wrote:
Actually, to use list::sort you can just provide the name of a function
to perform the comparison:

bool CompareSongs( const Song * leftSong, const Song * rightSong)
{
return leftSong->m_filename < rightSong->m_filename;
}

int main()
{
...
pSongsList->sort( CompareSongs );
...
}


Yes. However, a function object (see my post with the compare struct) is
usually faster.

Aug 17 '05 #9
On 17 Aug 2005 02:25:34 -0700, "Greg" <gr****@pacbell.net> wrote:

Actually, to use list::sort you can just provide the name of a function
to perform the comparison:

bool CompareSongs( const Song * leftSong, const Song * rightSong)
{
return leftSong->m_filename < rightSong->m_filename;
}

int main()
{
...
pSongsList->sort( CompareSongs );
...
}

Greg


I get this compile error. Maybe M$ implentation of <list> is broken,
mentioned in a previous post. I'm using MS VC++ 6.0

: error C2664: 'void __thiscall std::list<class Song *,class
std::allocator<class Song *> >::sort(struct std::greater<class Song
*>)' : cannot convert parameter 1 from 'bool
(const class Song *,const class Song *)' to 'struct
std::greater<class Song *>'
No constructor could take the source type, or constructor
overload resolution was ambiguous
Aug 17 '05 #10
Jeff wrote:
[...]
I get this compile error. Maybe M$ implentation of <list> is broken,
Yes, it is. And the reason is simple: very bad support in VC++ v6 for
member templates.
mentioned in a previous post. I'm using MS VC++ 6.0

[..]


Upgrade to 7.1
Aug 17 '05 #11
On Wed, 17 Aug 2005 15:28:30 -0400, Victor Bazarov
<v.********@comAcast.net> wrote:
Jeff wrote:
[...]
I get this compile error. Maybe M$ implentation of <list> is broken,


Yes, it is. And the reason is simple: very bad support in VC++ v6 for
member templates.
mentioned in a previous post. I'm using MS VC++ 6.0

[..]


Upgrade to 7.1


Thanks. That is exactly what I will do.
Aug 17 '05 #12
Jeff wrote:
On 17 Aug 2005 02:25:34 -0700, "Greg" <gr****@pacbell.net> wrote:
Actually, to use list::sort you can just provide the name of a function
to perform the comparison:

bool CompareSongs( const Song * leftSong, const Song * rightSong)
{
return leftSong->m_filename < rightSong->m_filename;
}

int main()
{
...
pSongsList->sort( CompareSongs );
...
}

Greg

I get this compile error. Maybe M$ implentation of <list> is broken,
mentioned in a previous post. I'm using MS VC++ 6.0

: error C2664: 'void __thiscall std::list<class Song *,class
std::allocator<class Song *> >::sort(struct std::greater<class Song
*>)' : cannot convert parameter 1 from 'bool
(const class Song *,const class Song *)' to 'struct
std::greater<class Song *>'
No constructor could take the source type, or constructor
overload resolution was ambiguous


I already answered that in another post in this thread.
It *is* possible with M$-VC++ 6.0

Stefan
Aug 18 '05 #13

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

Similar topics

6
by: praba kar | last post by:
Dear All, I have doubt regarding sorting. I have a list that list have another list (eg) list = ,,] I want to sort only numeric value having array field. How I need to do for that.
18
by: Matthias Kaeppler | last post by:
Hi, in my program, I have to sort containers of objects which can be 2000 items big in some cases. Since STL containers are based around copying and since I need to sort these containers quite...
1
by: aredo3604gif | last post by:
On Sun, 10 Apr 2005 19:46:32 GMT, aredo3604gif@yahoo.com wrote: >The user can dynamically enter and change the rule connection between >objects. The rule is a "<" and so given two objects: >a <...
25
by: Dan Stromberg | last post by:
Hi folks. Python appears to have a good sort method, but when sorting array elements that are very large, and hence have very expensive compares, is there some sort of already-available sort...
9
by: Daz | last post by:
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
16
by: Kittyhawk | last post by:
I would like to sort an Arraylist of objects on multiple properties. For instance, I have a Sort Index property and an ID property (both integers). So, the results of my sort would look like this:...
4
by: semedao | last post by:
Hi, I want to implement list of key-values that can be sort by 2 ways. let's say that in the first step I wanted to make SortList based on Key = int index that cannot change and Value is another...
3
by: Harry Haller | last post by:
Hello, I want to implement a generic list which will be used to display 7 columns in a GridView. One should be able to sort, filter and page each of the 7 columns. Ideally the filter should be...
2
by: Jason | last post by:
Hi folks-- Basically, I have a pressing need for a combination of 5.2 "Sorting a List of Strings Case-Insensitively" & 5.3 "Sorting a List of Objects by an Attribute of the Objects" from the...
3
by: =?Utf-8?B?U2NvdHQ=?= | last post by:
Good afternoon, I would like to mimic the sorting capabilities in Excel where I can sort a list by up to four properties (columns in excel). I would like to pass a collection of objects to a...
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
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
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
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
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...
0
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new...

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.