digitalmars.D.learn - Sorting structs?

• Boomerang (14/14) Jan 29 2014 Hello everybody. I'm trying to learn D by solving simple
• Benjamin Thaut (22/36) Jan 29 2014 You can either overload the compare operator for the struct
• Stanislav Blinov (13/15) Jan 29 2014 This can be solved without sorting in reverse or overloading
• Stanislav Blinov (8/8) Jan 29 2014 It's also worth noting that you can avoid passing structs into
• Boomerang (4/4) Jan 29 2014 Thanks for the help so far.
• Boomerang (4/4) Jan 29 2014 Also sorry for double posting but I'm confused how the sorting
• Stanislav Blinov (67/71) Jan 29 2014 On Wednesday, 29 January 2014 at 10:30:06 UTC, Boomerang wrote:
• Tobias Pankrath (3/6) Jan 29 2014 Did you test this one? std.algorithm.map is lazy.
• Stanislav Blinov (4/11) Jan 29 2014 Ah yes, sorry, my bad. I forgot to remove foreach during testing
• Paul-Andre (4/7) Jan 29 2014 I am new to D.
• Jesse Phillips (3/10) Jan 29 2014 in is the same as 'scope const' (scope checks aren't implemented)
"Boomerang" <nomailforme nomailforme.no> writes:
```Hello everybody. I'm trying to learn D by solving simple
exercises.

print the names of students in descending order of their grades.

In C++, I would define a Student struct, overload the operators:
bool operator<(const Student&, const Student&)
std::istream& operator>>(std::istream&, Student&)

Then I'd store the Students in let's say a std::vector, sort it
in reverse, then print it accordingly.

But I don't know how to do things in D. I'm reading Cehreli's
book, so far I've only finished its first trinity (just before
struct).

I would appreciate it if you explained your approach and gave
source code illustrating it. Thanks!
```
Jan 29 2014
Benjamin Thaut <code benjamin-thaut.de> writes:
```Am 29.01.2014 10:33, schrieb Boomerang:
Hello everybody. I'm trying to learn D by solving simple
exercises.

print the names of students in descending order of their grades.

In C++, I would define a Student struct, overload the operators:
bool operator<(const Student&, const Student&)
std::istream& operator>>(std::istream&, Student&)

Then I'd store the Students in let's say a std::vector, sort it
in reverse, then print it accordingly.

But I don't know how to do things in D. I'm reading Cehreli's
book, so far I've only finished its first trinity (just before
struct).

I would appreciate it if you explained your approach and gave
source code illustrating it. Thanks!

You can either overload the compare operator for the struct

struct bla
{
int i;
int opCmp(ref const(bla) rh)
{
if(this.i < rh.i)
return -1;
if(this.i > rh.i)
return 1;
return 0;
}
}

or you could just pass a different compare less expression to sort

bla[] arrayToSort;
sort!"a.i < b.i"(arrayToSort);

You can also pass a lambda or any function as compare less function to
sort:
sort!((a,b){return a.i < b.i;})(arrayToSort);

Kind Regards
Benjamin Thaut
```
Jan 29 2014
"Stanislav Blinov" <stanislav.blinov gmail.com> writes:
```On Wednesday, 29 January 2014 at 09:33:50 UTC, Boomerang wrote:

I would appreciate it if you explained your approach and gave
source code illustrating it. Thanks!

anything in C++ (with a predicate version of sort() algorithm),
and in D too. Take a look at this code:

http://dpaste.dzfl.pl/2d0dd6f953dc

the std.algorithm.sort() takes an optional predicate (as a
template argument) to resolve the order of elements. In this
case, it is specified as an anonymous function

You could alternatively specify it as a string:

or like this:

```
Jan 29 2014
"Stanislav Blinov" <stanislav.blinov gmail.com> writes:
```It's also worth noting that you can avoid passing structs into
predicate function by value, and instead pass them by reference:

This is useful for "heavy" structs to save on performance. E.g.
in this case, Student.sizeof is 24 bytes on 64 bit machine.
Passing by reference will only need to copy 16 bytes (i.e. size
of two pointers), whereas passing by value will incur copying 48
bytes (two structs).
```
Jan 29 2014
"Boomerang" <nomailforme nomailforme.no> writes:
```Thanks for the help so far.
My current code is here: http://dpaste.dzfl.pl/b9acff399649

Are there problems with my code, or do you have suggestions to
improve it?
```
Jan 29 2014
"Boomerang" <nomailforme nomailforme.no> writes:
```Also sorry for double posting but I'm confused how the sorting
works when we only specify to be sorted by grade. I think in C++,
disregarding other data members can lead to loss of data in
things such as std::set.
```
Jan 29 2014
"Stanislav Blinov" <stanislav.blinov gmail.com> writes:
```On Wednesday, 29 January 2014 at 10:30:06 UTC, Boomerang wrote:

import std.algorithm;
import std.stdio;
import std.array;

void main()
{
struct Student
{
string name;
}

Student[] studs;

writeln("Enter student data. Reading stops when student name
is empty.");

while (true)
{
// Calls to readf() may throw an exception
// if user inputs invalid data.
// You may want to consider accounting
// for that.

typeof(Student.name) name;
write("Student name: ");

// Don't burden users with typing STOP :)
if (name.empty)
break;

import std.exception;
import std.conv : ConvException;
// EXAMPLE: catch all ConvExceptions
// to persuade user to input a number :)
{
// Conversion failed but there's still data in
// stdin. We get rid of it:
}

// Create Student only when necessary
// (a good compiler will optimize that
// to avoid copying):
}

// Use anonymous function with explicit
// parameter storage class specifier;
// Also Use UFCS

// You can omit type name in foreach;
// also it's worth using ref const to avoid
// unnecessary copies
foreach (ref const s; studs)
writeln(s.name);

// Or avoid foreach altogether:
studs.map!((ref const s) => writeln(s.name));
}

Also sorry for double posting but I'm confused how the sorting
works when we only specify to be sorted by grade. I think in
C++, disregarding other data members can lead to loss of data
in things such as std::set.

Yes and no. In fact, std::set is by default instantiated with an
std::less predicate. But std::set is intended to store unique
elements. So if you try to insert an element that std::set
already considers to exist (it uses the predicate to determine
that), it doesn't insert it.

But you must understand that despite being generic, algorithms
and containers still serve particular purposes. You wouldn't
store students in a set unless you had some way to uniquely
identify them :)
```
Jan 29 2014
"Tobias Pankrath" <tobias pankrath.net> writes:
```On Wednesday, 29 January 2014 at 11:24:54 UTC, Stanislav Blinov
wrote:
// Or avoid foreach altogether:
studs.map!((ref const s) => writeln(s.name));
}

Did you test this one? std.algorithm.map is lazy.
```
Jan 29 2014
"Stanislav Blinov" <stanislav.blinov gmail.com> writes:
```On Wednesday, 29 January 2014 at 12:44:37 UTC, Tobias Pankrath
wrote:
On Wednesday, 29 January 2014 at 11:24:54 UTC, Stanislav Blinov
wrote:
// Or avoid foreach altogether:
studs.map!((ref const s) => writeln(s.name));
}

Did you test this one? std.algorithm.map is lazy.

Ah yes, sorry, my bad. I forgot to remove foreach during testing
and assumed it worked. Facepalm m)
```
Jan 29 2014
"Paul-Andre" <chapeaufeutre gmail.com> writes:
```On Wednesday, 29 January 2014 at 11:24:54 UTC, Stanislav Blinov
wrote:
On Wednesday, 29 January 2014 at 10:30:06 UTC, Boomerang wrote:
// also it's worth using ref const to avoid
// unnecessary copies

I am new to D.
Why should someone use "ref const" instead of "in"?
```
Jan 29 2014
"Jesse Phillips" <Jesse.K.Phillips+D gmail.com> writes:
```On Thursday, 30 January 2014 at 03:00:43 UTC, Paul-Andre wrote:
On Wednesday, 29 January 2014 at 11:24:54 UTC, Stanislav Blinov
wrote:
On Wednesday, 29 January 2014 at 10:30:06 UTC, Boomerang wrote:
// also it's worth using ref const to avoid
// unnecessary copies

I am new to D.
Why should someone use "ref const" instead of "in"?

in is the same as 'scope const' (scope checks aren't implemented)
So you be relying on the optimizer to not copy.
```
Jan 29 2014