Jump to page: 1 2
Thread overview
Sort in return statement
Dec 09
rjframe
Dec 09
SimonN
Dec 09
user1234
Dec 09
Seb
Dec 09
rjframe
Dec 09
Seb
Dec 09
Seb
December 09
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. */

}

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

December 09
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
December 09
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.


December 09
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
December 09
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;
}

// -------
December 09
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
}
```
December 09
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;
```

December 09
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.
December 09
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
December 09
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);
}
// -----------


« First   ‹ Prev
1 2