www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Sort in return statement

reply codephantom <me noyb.com> writes:
Anyone got ideas on how to get sort() working in the *return* 
statement?

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

ushort[] draw8Numbers()
{
     import std.meta : aliasSeqOf;
     import std.range : iota;
     ushort[] numbers = [ aliasSeqOf!(iota(1,46)) ];

     import std.random : randomShuffle;
     randomShuffle(numbers);

     import std.range : take;
     import std.algorithm.sorting : sort;
     return numbers.take(8); /* ok */
     //return sort(numbers.take(8)); /* I want this, but it won't 
work. */

}

// -------------
Dec 08 2017
parent reply rjframe <dlang ryanjframe.com> writes:
On Sat, 09 Dec 2017 02:34:29 +0000, codephantom wrote:

 Anyone got ideas on how to get sort() working in the *return*
 statement?
 
 //------------
 
 ushort[] draw8Numbers()
 {
      import std.meta : aliasSeqOf;
      import std.range : iota;
      ushort[] numbers = [ aliasSeqOf!(iota(1,46)) ];
 
      import std.random : randomShuffle;
      randomShuffle(numbers);
 
      import std.range : take;
      import std.algorithm.sorting : sort;
      return numbers.take(8); /* ok */
      //return sort(numbers.take(8)); /* I want this, but it won't
 work. */
 
 }
 
 // -------------
`sort` returns a SortedRange of ushorts, not an array of ushorts. Make it: ``` import std.array : array; return sort(numbers.take(8)).array; ``` --Ryan
Dec 08 2017
next sibling parent reply codephantom <me noyb.com> writes:
On Saturday, 9 December 2017 at 02:45:35 UTC, rjframe wrote:
 `sort` returns a SortedRange of ushorts, not an array of 
 ushorts. Make it:

 ```
 import std.array : array;
 return sort(numbers.take(8)).array;
 ```

 --Ryan
That's it! Thanks Ryan.
Dec 08 2017
next sibling parent reply SimonN <eiderdaus gmail.com> writes:
On Saturday, 9 December 2017 at 03:24:52 UTC, codephantom wrote:
 On Saturday, 9 December 2017 at 02:45:35 UTC, rjframe wrote:
 `sort` returns a SortedRange of ushorts, not an array of 
 ushorts. Make it:

 ```
 import std.array : array;
 return sort(numbers.take(8)).array;
 ```

 --Ryan
That's it! Thanks Ryan.
Yes, this works, and your algorithm would even accept arbitary random-access ranges, not merely arrays. But since we start explicitly with a ushort[] that this function has allocated just for this algorithm, we could save the extra allocation by the final call to array(). // ushort[] numbers = ... randomShuffle(numbers); import std.algorithm.sorting : sort; numbers = numbers[0 .. 8]; sort(numbers); return numbers; sort(numbers) does two things: (1) affect the underlying data, (2) return an input range with extra information that this returned range is sorted. But in our example, we don't need to allocate a fresh array from (2). We can return the sorted data from (1), this is already in array-form. -- Simon
Dec 08 2017
parent codephantom <me noyb.com> writes:
On Saturday, 9 December 2017 at 04:31:33 UTC, SimonN wrote:
 Yes, this works, and your algorithm would even accept arbitary 
 random-access ranges, not merely arrays.
Would be nice if I could do it all as a 'one liner': // -------- int[] draw8Numbers() { import std.algorithm.sorting : sort; import std.random : randomShuffle; import std.meta : aliasSeqOf; import std.range : iota; import std.range : take; import std.array : array; // return a sorted array of 8 random numbers, between 1..45 inclusive. return sort(randomShuffle([ aliasSeqOf!(iota(1,46)) ]).take(8)).array; } // -------
Dec 08 2017
prev sibling parent user1234 <user1234 12.nl> writes:
On Saturday, 9 December 2017 at 03:24:52 UTC, codephantom wrote:
 On Saturday, 9 December 2017 at 02:45:35 UTC, rjframe wrote:
 `sort` returns a SortedRange of ushorts, not an array of 
 ushorts. Make it:

 ```
 import std.array : array;
 return sort(numbers.take(8)).array;
 ```

 --Ryan
That's it! Thanks Ryan.
You can also return a lazy range: ``` auto draw8Numbers() { import std.meta : aliasSeqOf; import std.range : iota, take; ushort[] numbers = [ aliasSeqOf!(iota(1,46)) ]; import std.random : randomShuffle; randomShuffle(numbers); import std.algorithm.sorting : sort; return sort(numbers[].take(8)); } void main() { import std.array; ushort[] nbrs = draw8Numbers.array; // evaluated after return, during assingment } ```
Dec 08 2017
prev sibling parent reply Seb <seb wilzba.ch> writes:
On Saturday, 9 December 2017 at 02:45:35 UTC, rjframe wrote:
 On Sat, 09 Dec 2017 02:34:29 +0000, codephantom wrote:

 Anyone got ideas on how to get sort() working in the *return*
 statement?
 
 //------------
 
 ushort[] draw8Numbers()
 {
      import std.meta : aliasSeqOf;
      import std.range : iota;
      ushort[] numbers = [ aliasSeqOf!(iota(1,46)) ];
 
      import std.random : randomShuffle;
      randomShuffle(numbers);
 
      import std.range : take;
      import std.algorithm.sorting : sort;
      return numbers.take(8); /* ok */
      //return sort(numbers.take(8)); /* I want this, but it 
 won't
 work. */
 
 }
 
 // -------------
`sort` returns a SortedRange of ushorts, not an array of ushorts. Make it: ``` import std.array : array; return sort(numbers.take(8)).array; ``` --Ryan
Use .release to obtain the underlying array. No need to do another allocation! ``` numbers.take(8).sort.release; ```
Dec 08 2017
parent reply rjframe <dlang ryanjframe.com> writes:
On Sat, 09 Dec 2017 07:32:42 +0000, Seb wrote:

 
 Use .release to obtain the underlying array. No need to do another
 allocation!
 
 ```
 numbers.take(8).sort.release;
 ```
I did not realize that was there; thanks.
Dec 09 2017
parent reply Seb <seb wilzba.ch> writes:
On Saturday, 9 December 2017 at 14:05:36 UTC, rjframe wrote:
 On Sat, 09 Dec 2017 07:32:42 +0000, Seb wrote:

 
 Use .release to obtain the underlying array. No need to do 
 another allocation!
 
 ```
 numbers.take(8).sort.release;
 ```
I did not realize that was there; thanks.
Yeah, you are very welcome. It's a bit hidden in the docs: https://dlang.org/phobos/std_range.html#SortedRange
Dec 09 2017
parent reply codephantom <me noyb.com> writes:
On Saturday, 9 December 2017 at 14:18:00 UTC, Seb wrote:
 Yeah, you are very welcome. It's a bit hidden in the docs:
Yes. Thanks for that. After lots of reading, and testing, I managed to get a simple, one liner ;-) (doesn't seem like .release is needed though.) // ----------- auto draw8Numbers() { import std.meta : aliasSeqOf; import std.range : iota; import std.random : randomSample; return randomSample([ aliasSeqOf!(iota(1,46)) ], 8); } // -----------
Dec 09 2017
parent reply Seb <seb wilzba.ch> writes:
On Saturday, 9 December 2017 at 14:42:44 UTC, codephantom wrote:
 After lots of reading, and testing, I managed to get a simple, 
 one liner ;-)
 (doesn't seem like .release is needed though.)
FYI .release is only possible on a SortedRange and then yields the underlying range. randomSample doesn't sort its returned range, but I am glad to hear this worked for you.
Dec 09 2017
parent codephantom <me noyb.com> writes:
On Saturday, 9 December 2017 at 14:49:28 UTC, Seb wrote:
 randomSample doesn't sort its returned range
Not by design, however, because it samples in the order that the elements appear, *if* those elements are already sorted (whether by design or explicately sorted), then the results of the randomsample are also implicitly already sorted ;-)
Dec 09 2017