Thread overview
Return complete multi-dimensional array after appending
Sep 15, 2021
eXodiquas
Sep 15, 2021
Paul Backus
Sep 15, 2021
eXodiquas
September 15, 2021

Howdy everyone. :)

Today I came across a small problem (I mean, I could solve it by writing a function that solves my problem, but maybe there is something in std that can help me here). Let's say we have the following code:

void main() {
  int[][] a = [[],[]];
  (a[0] ~ 5).writeln; // => [5]
}

it's quite obvious that [5] is printed. Because I am a fan of one-liners (we do small code challenges, and I want to show what's possible with fold) and ridiculous stuff I tried to do something like this:

[1,0,3,4,0,5]
.fold!((a, e) => e != 0 ? a[0] ~ e : a[1] ~ e)(cast(int[][]) [[],[]])
.flatten
.writeln

This should sort all non 0s into the a[0] array and all 0s into the a[1] array. But it won't work because the ~ does not return the whole array (which is probably better for most of the cases). So the question, is there a way to do this kind of append, but getting the whole array back as a result in std?
And another question, is there a way to tell fold about the initial value of an empty list without having to cast a void[] into the list of the desired type?

Thanks in advance. :)

eXodiquas

September 15, 2021

On Wednesday, 15 September 2021 at 20:32:12 UTC, eXodiquas wrote:

>
[1,0,3,4,0,5]
.fold!((a, e) => e != 0 ? a[0] ~ e : a[1] ~ e)(cast(int[][]) [[],[]])
.flatten
.writeln

This should sort all non 0s into the a[0] array and all 0s into the a[1] array. But it won't work because the ~ does not return the whole array (which is probably better for most of the cases). So the question, is there a way to do this kind of append, but getting the whole array back as a result in std?

You need to use ~= instead of ~ to mutate an existing array:

import std;

void main()
{
    [1, 0, 3, 4, 0, 5]
        .fold!((a, e) {
            e != 0 ? (a[0] ~= e) : (a[1] ~= e);
            return a;
        })(cast(int[][]) [[], []])
        .joiner
        .writeln;
}

Of course, a more idiomatic solution would be to use std.algorithm.partition:

import std;

void main()
{
    auto arr = [1, 0, 3, 4, 0, 5];
    arr.partition!(e => e != 0); // in-place
    arr.writeln;
}
September 15, 2021

On Wednesday, 15 September 2021 at 21:02:29 UTC, Paul Backus wrote:

>

On Wednesday, 15 September 2021 at 20:32:12 UTC, eXodiquas wrote:

>
[1,0,3,4,0,5]
.fold!((a, e) => e != 0 ? a[0] ~ e : a[1] ~ e)(cast(int[][]) [[],[]])
.flatten
.writeln

This should sort all non 0s into the a[0] array and all 0s into the a[1] array. But it won't work because the ~ does not return the whole array (which is probably better for most of the cases). So the question, is there a way to do this kind of append, but getting the whole array back as a result in std?

You need to use ~= instead of ~ to mutate an existing array:

import std;

void main()
{
    [1, 0, 3, 4, 0, 5]
        .fold!((a, e) {
            e != 0 ? (a[0] ~= e) : (a[1] ~= e);
            return a;
        })(cast(int[][]) [[], []])
        .joiner
        .writeln;
}

Of course, a more idiomatic solution would be to use std.algorithm.partition:

import std;

void main()
{
    auto arr = [1, 0, 3, 4, 0, 5];
    arr.partition!(e => e != 0); // in-place
    arr.writeln;
}

Oooh, I totally forgot you can open blocks like this in anonymous functions. Now I look a bit stupid. Thanks. :) partition is also very nice. D std is so huge, I should sketch out a roadmap or something. That's why I asked the question in the first place because deep inside I knew there is a function in std that solves the problem.

Thanks for the answer. :)