Thread overview
D slicing
Jun 17, 2013
Colin Grogan
Jun 17, 2013
bearophile
Jun 17, 2013
Andrej Mitrovic
Jun 17, 2013
Ali Çehreli
Jun 18, 2013
Colin Grogan
June 17, 2013
Hi all.

Wondering what way I'd go about this, I want to slice an array into two arrays. First array containing every even index (i.e. 0,2,4,6,8..$)
Second slice containing every odd index (i.e. 1,3,5,7,9..$) <-- be some issue with using $ depending on if orig length is odd or even. Can work that out easily enough...

Reading the articles on array slicing its not clear if its possible.

Ideally, I could do something like the following:

auto orig = [1,2,3,4,5,6,7];
auto sliceEven = orig[0..$..2];
auto sliceOdd = orig[1..$..2];

But I dont think thats possible?

Any idears?
June 17, 2013
Colin Grogan:

> Reading the articles on array slicing its not clear if its possible.

I presume Walter thinks that slicing with a stride is a not common enough operation to put it into D. His choices on such things are a bit arbitrary.

One way to do it:


import std.stdio, std.array, std.range;

void main() {
    auto orig = [1, 2, 3, 4, 5, 6, 7];
    auto sliceOdd = orig.stride(2).array;
    sliceOdd.writeln;
    auto sliceEven = orig[1..$].stride(2).array;
    sliceEven.writeln;
}


stride() is just a function used with UFCS.

Don't use ".array" if you just need a lazy sequence.

Bye,
bearophile
June 17, 2013
On Monday, 17 June 2013 at 23:34:46 UTC, Colin Grogan wrote:
> auto orig = [1,2,3,4,5,6,7];
> auto sliceEven = orig[0..$..2];
> auto sliceOdd = orig[1..$..2];
>

> But I dont think thats possible?

Not with arrays, they must be contiguous. But you can use ranges instead:

-----
import std.stdio;
import std.range;

void main()
{
    auto orig = [1,2,3,4,5,6,7];
    auto sliceEven = orig.stride(2);
    auto sliceOdd = orig.drop(1).stride(2);

    writeln(sliceEven);
    writeln(sliceOdd);
}
-----

You can convert the ranges into arrays by calling .array on them (and importing std.array first), but this will cause allocations.
June 17, 2013
On 06/17/2013 04:34 PM, Colin Grogan wrote:

> Wondering what way I'd go about this, I want to slice an array into two
> arrays. First array containing every even index (i.e. 0,2,4,6,8..$)
> Second slice containing every odd index (i.e. 1,3,5,7,9..$) <-- be some
> issue with using $ depending on if orig length is odd or even. Can work
> that out easily enough...
>
> Reading the articles on array slicing its not clear if its possible.
>
> Ideally, I could do something like the following:
>
> auto orig = [1,2,3,4,5,6,7];
> auto sliceEven = orig[0..$..2];
> auto sliceOdd = orig[1..$..2];

If you want the data sit where it is but simply have different views in it, then you must use ranges. There are multiple ways.

Here is one using std.range.stride:

import std.stdio;
import std.range;

void main()
{
    auto orig = [0, 1, 2, 3, 4, 5, 6, 7];

    auto sliceEven = orig.stride(2);
    auto sliceOdd = orig.dropOne.stride(2);

    writeln(sliceEven);
    writeln(sliceOdd);
}

The output:

[0, 2, 4, 6]
[1, 3, 5, 7]

Or you can generate the indexes and then get a view that way:

    auto sliceEven = orig.indexed(iota(0, orig.length, 2));
    auto sliceOdd = orig.indexed(iota(1, orig.length, 2));

Ali

June 18, 2013
On Monday, 17 June 2013 at 23:48:36 UTC, Ali Çehreli wrote:
> On 06/17/2013 04:34 PM, Colin Grogan wrote:
>
> > Wondering what way I'd go about this, I want to slice an
> array into two
> > arrays. First array containing every even index (i.e.
> 0,2,4,6,8..$)
> > Second slice containing every odd index (i.e. 1,3,5,7,9..$)
> <-- be some
> > issue with using $ depending on if orig length is odd or
> even. Can work
> > that out easily enough...
> >
> > Reading the articles on array slicing its not clear if its
> possible.
> >
> > Ideally, I could do something like the following:
> >
> > auto orig = [1,2,3,4,5,6,7];
> > auto sliceEven = orig[0..$..2];
> > auto sliceOdd = orig[1..$..2];
>
> If you want the data sit where it is but simply have different views in it, then you must use ranges. There are multiple ways.
>
> Here is one using std.range.stride:
>
> import std.stdio;
> import std.range;
>
> void main()
> {
>     auto orig = [0, 1, 2, 3, 4, 5, 6, 7];
>
>     auto sliceEven = orig.stride(2);
>     auto sliceOdd = orig.dropOne.stride(2);
>
>     writeln(sliceEven);
>     writeln(sliceOdd);
> }
>
> The output:
>
> [0, 2, 4, 6]
> [1, 3, 5, 7]
>
> Or you can generate the indexes and then get a view that way:
>
>     auto sliceEven = orig.indexed(iota(0, orig.length, 2));
>     auto sliceOdd = orig.indexed(iota(1, orig.length, 2));
>
> Ali

Thats perfect folks. Should have known to look in std.range.
This works for me perfectly.

3 answers all within a couple minutes of each other, what a good community! ;)