Thread overview | |||||||
---|---|---|---|---|---|---|---|
|
May 08, 2011 Getting equivalent elements in a range/array | ||||
---|---|---|---|---|
| ||||
I want to turn this: auto arr = [1, 1, 2, 3, 4, 4]; into this: auto arr2 = [[1, 1], [2], [3], [4, 4]]; I want an array of arrays of the same elements. Lazy or not, I don't care. I thought I could get away with this inside some while loop: auto equals = array(filter!"a == b"(arr)); arr = arr[equals.length-1..$]; Nope. I need this for some buffered output, where the requirement is the elements of the buffer all need to have the same properties so a function can output a buffer of elements in one call instead of calling the function for each element (the function call is expensive). |
May 08, 2011 Re: Getting equivalent elements in a range/array | ||||
---|---|---|---|---|
| ||||
Posted in reply to Andrej M. | On 05/07/2011 09:07 PM, Andrej M. wrote:
> I want to turn this:
> auto arr = [1, 1, 2, 3, 4, 4];
>
> into this:
> auto arr2 = [[1, 1], [2], [3], [4, 4]];
>
> I want an array of arrays of the same elements. Lazy or not, I don't care.
>
> I thought I could get away with this inside some while loop:
> auto equals = array(filter!"a == b"(arr));
> arr = arr[equals.length-1..$];
>
> Nope.
>
> I need this for some buffered output, where the requirement is the elements of the buffer all need to have the same properties so a function can output a buffer of elements in one call instead of calling the function for each element (the function call is expensive).
This seems to work, but needs more work. :)
import std.stdio;
import std.array;
struct EquivalentElements
{
int[] range;
int[] front_;
this(int[] range)
{
this.range = range;
this.front_ = popEqualFront(this.range);
}
bool empty()
{
return front_.empty;
}
int[] front()
{
return front_;
}
void popFront()
{
this.front_ = popEqualFront(this.range);
}
private int[] popEqualFront(ref int[] range)
{
int[] front;
if (!range.empty) {
do {
front ~= range[0];
range = range[1..$];
} while (!range.empty &&
(front[$-1] == range[0]));
}
return front;
}
}
void main()
{
writeln(EquivalentElements([1, 1, 2, 3, 4, 4]));
}
|
May 08, 2011 Re: Getting equivalent elements in a range/array | ||||
---|---|---|---|---|
| ||||
Posted in reply to Ali Çehreli | Fantastic work, thanks! I'll look into more detail tomorrow, but it looks good so far. Just added a function helper and made the struct typed: import std.array; import std.range; struct EquivalentElements(T) { T range; T front_; this(T range) { this.range = range; this.front_ = popEqualFront(this.range); } bool empty() { return front_.empty; } T front() { return front_; } void popFront() { this.front_ = popEqualFront(this.range); } private T popEqualFront(ref T range) { T front; if (!range.empty) { do { front ~= range[0]; range = range[1..$]; } while (!range.empty && (front[$-1] == range[0])); } return front; } } EquivalentElements!(Range) equivalentElements(Range)(Range r) { return typeof(return)(r); } // test void main() { foreach (elem; equivalentElements([1, 1, 2, 3, 4, 4])) { writeln(elem); } } |
May 08, 2011 Re: Getting equivalent elements in a range/array | ||||
---|---|---|---|---|
| ||||
Posted in reply to Andrej M. | Andrej M.:
> I want to turn this:
> auto arr = [1, 1, 2, 3, 4, 4];
>
> into this:
> auto arr2 = [[1, 1], [2], [3], [4, 4]];
>
> I want an array of arrays of the same elements. Lazy or not, I don't care.
Currently if you use group like this:
writeln(arr.group());
You get:
[Tuple!(int,uint)(1, 2), Tuple!(int,uint)(2, 1), Tuple!(int,uint)(3, 1), Tuple!(int,uint)(4, 2)]
Andrei has recently said he wants to modify group() to make it work more like python itertools.groupby(), so it will do what you want (the duplicated items too will be lazy, as in Python).
Bye,
bearophile
|
May 08, 2011 Re: Getting equivalent elements in a range/array | ||||
---|---|---|---|---|
| ||||
Posted in reply to bearophile | Thanks, group seems to work fine too. |
Copyright © 1999-2021 by the D Language Foundation