Re: Function which returns a sorted array without duplicates

2023-01-22 Thread Salih Dincer via Digitalmars-d-learn

On Sunday, 22 January 2023 at 23:26:45 UTC, dan wrote:


So what i was missing was std.array.


Of course you can use the uniq from Phobos.  But since we already 
use array, you should also try the 3rd classic version:


```d
import std.algorithm;
import std.array;

// qef. version:
private S[] sortArray ( S )( S[] x )
{
  auto y = x.dup;
  return y.sort.uniq.array;
}

// no dup. version:
private S[] sortArrayy ( S )( S[] x )
{
  S[] w;
  foreach ( v ; x ) w ~= v;
  return w.sort.uniq.array;
}

// classic version:
private S[] sortArrayyy ( S )( S[] x )
{
  S[] w = x.dup;
  w.sort;

  size_t diff;
  for (size_t j, i = 1; i < w.length; ++i) {
if (w[j] != w[i]) {
  w[++j] = w[i];
} else {
  ++diff;
}
  }
  return w[0 .. $ - diff];
}

void main()
{
  uint[] nums = [1, 3, 2, 5, 1, 4, 2, 8];

  auto sorted = nums.sortArray;
  assert(sorted.equal(nums.sortArrayy));
  assert(sorted.equal(nums.sortArrayyy));

  import std.stdio;
  writeln( "Input:  ", nums );
  writeln( "Output: ", sorted );
}
```

In fine, we have implemented 3 ways to sort an array and return 
it without repetition. I guess, there is no alternative to this 
basic algorithm...


SDB@79


Re: Function which returns a sorted array without duplicates

2023-01-22 Thread dan via Digitalmars-d-learn

On Sunday, 22 January 2023 at 07:33:01 UTC, evilrat wrote:

On Sunday, 22 January 2023 at 04:42:09 UTC, dan wrote:
I would like to write a function which takes an array as 
input, and returns a sorted array without duplicates.



```d
private S[] _sort_array( S )( S[] x ) {
  import std.algorithm;
  auto y = x.dup;
  y.sort;
  auto z = y.uniq;
  // Cannot just return z; this gives:
  // Error: cannot implicitly convert expression `z` of 
type

  // `UniqResult!(binaryFun, uint[])` to `uint[]`


uniq and other algorithms often returns a lazy range, you can 
build an array by using `std.array.array()`


https://dlang.org/phobos/std_array.html#array

try something like this or just `return array(y.uniq);`

```d
private S[] _sort_array( S )( S[] x ) {
import std.algorithm;
import std.array;
return x.dup
   .sort
   .uniq
   .array();
}
```

And IIRC you probably don't need `dup` as sort produces a lazy 
range.


Thanks evilrat, this works perfectly, and is just the right style 
too (imvho).


So what i was missing was std.array.

Thanks also Ali for your subsequent clarifying remarks.

(Probably what i need to do is read a good book on the std 
library for d.)


dan

Thanks also Ali for your subsequent remarks


Re: Function which returns a sorted array without duplicates

2023-01-22 Thread Ali Çehreli via Digitalmars-d-learn

On 1/21/23 23:33, evilrat wrote:

> And IIRC you probably don't need `dup`

Unfortunately, no. Skipping .dup is only possible if we are allowed to 
sort the original array.


> as sort produces a lazy range.

sort() returns a SortedRange but it can't be lazy. Even if it were, the 
first call to .front would have to sort anyway. However...


There is an optimization possible for such requirements if not all 
elements but just a number of them are needed. For example, if only the 
first 10 elements are needed, then a binary heap may be faster:


  https://dlang.org/phobos/std_container_binaryheap.html

The usage would be similar to the following for "the first 10 unique 
elements":


  heapify(arr).uniq.take(10)

(Not tested.)

Ali



Re: Function which returns a sorted array without duplicates

2023-01-21 Thread evilrat via Digitalmars-d-learn

On Sunday, 22 January 2023 at 04:42:09 UTC, dan wrote:
I would like to write a function which takes an array as input, 
and returns a sorted array without duplicates.



```d
private S[] _sort_array( S )( S[] x ) {
  import std.algorithm;
  auto y = x.dup;
  y.sort;
  auto z = y.uniq;
  // Cannot just return z; this gives:
  // Error: cannot implicitly convert expression `z` of type
  // `UniqResult!(binaryFun, uint[])` to `uint[]`


uniq and other algorithms often returns a lazy range, you can 
build an array by using `std.array.array()`


https://dlang.org/phobos/std_array.html#array

try something like this or just `return array(y.uniq);`

```d
private S[] _sort_array( S )( S[] x ) {
import std.algorithm;
import std.array;
return x.dup
   .sort
   .uniq
   .array();
}
```

And IIRC you probably don't need `dup` as sort produces a lazy 
range.






Function which returns a sorted array without duplicates

2023-01-21 Thread dan via Digitalmars-d-learn
I would like to write a function which takes an array as input, 
and returns a sorted array without duplicates.


In fact, i have a function which does this, but i think it may 
have some extra unnecessary steps.


```d
private S[] _sort_array( S )( S[] x ) {
  import std.algorithm;
  auto y = x.dup;
  y.sort;
  auto z = y.uniq;
  // Cannot just return z; this gives:
  // Error: cannot implicitly convert expression `z` of type
  // `UniqResult!(binaryFun, uint[])` to `uint[]`
  //
  // You also cannot just return cast( S[] ) z;
  //
  // Nor can you do:
  //  import std.conv;
  //  return to!( S[] )( z );
  typeof( x ) w;
  foreach ( v ; z ) w ~= v;
  return w;
}
```

My only constraint is that i really want to keep the same 
signature (i.e., return an array, not sharing structure or 
storage with the input).


Here's the usage:

```d
void main( ) {
  uint[] nums = [1, 3, 2, 5, 1, 4, 2, 8];
  auto sorted = _sort_array( nums );
  import std.stdio;
  writeln( "Input:  ", nums );
  writeln( "Output: ", sorted );
}
```

Thanks in advance for any info!

dan