Skip to content
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 27 additions & 5 deletions std/algorithm/iteration.d
Original file line number Diff line number Diff line change
Expand Up @@ -1093,7 +1093,8 @@ Params:

Returns:
$(D filter!(predicate)(range)) returns a new range containing only elements $(D x) in $(D range) for
which $(D predicate(x)) returns $(D true).
which $(D predicate(x)) returns $(D true). If a `SortedRange` is passed, the result is going to be
a `SortedRange`.

See_Also:
$(HTTP en.wikipedia.org/wiki/Filter_(higher-order_function), Filter (higher-order function))
Expand All @@ -1103,7 +1104,11 @@ if (is(typeof(unaryFun!predicate)))
{
auto filter(Range)(Range range) if (isInputRange!(Unqual!Range))
{
return FilterResult!(unaryFun!predicate, Range)(range);
import std.range : SortedRange, assumeSorted;
static if (is(Range : SortedRange!TT, TT))
return assumeSorted(FilterResult!(unaryFun!predicate, Range)(range));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The sorting predicate should be propagated here, e.g. return FilterResult!(unaryFun!predicate, Range)(range).assumeSorted!TT;

else
return FilterResult!(unaryFun!predicate, Range)(range);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code is repetitive here, should be something like:

auto result = FilterResult!(unaryFun!predicate, Range)(range);
static if (is(Range : SortedRange!order, order))
    return result.assumeSorted!order;
else
    return result;

}
}

Expand Down Expand Up @@ -1259,6 +1264,11 @@ private struct FilterResult(alias pred, Range)
auto arr = [1,2,3,4,5];
auto m = map!"a + 1"(filter!"a < 4"(arr));
assert(equal(m, [2, 3, 4]));

// Issue 9682
import std.range : SortedRange, assumeSorted;
auto t = assumeSorted([1, 2, 3, 4, 5]);
assert(equal(filter!(a => a > 3)(t), assumeSorted([4, 5])));
}

@safe unittest
Expand Down Expand Up @@ -1414,14 +1424,19 @@ Params:
Returns: A range of elements of type $(D Tuple!(ElementType!R, uint)),
representing each consecutively unique element and its respective number of
occurrences in that run. This will be an input range if $(D R) is an input
range, and a forward range in all other cases.
range, and a forward range in all other cases. If a `SortedRanged` is passed,
the result is going to be a `SortedRange`.

See_Also: $(LREF chunkBy), which chunks an input range into subranges
of equivalent adjacent elements.
*/
Group!(pred, Range) group(alias pred = "a == b", Range)(Range r)
auto group(alias pred = "a == b", Range)(Range r)
{
return typeof(return)(r);
import std.range : SortedRange, assumeSorted;
static if (is(Range : SortedRange!TT, TT))
return assumeSorted(Group!(pred, Range)(r));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same as above

else
return Group!(pred, Range)(r);
}

/// ditto
Expand Down Expand Up @@ -1598,6 +1613,13 @@ if (isInputRange!R)
const(int[][]) a6 = [[1], [1]];
auto g6 = a6.group;
assert(equal(g6.front[0], [1]));

// Issue 9682
import std.range : SortedRange, assumeSorted;
auto a7 = assumeSorted([1, 1, 2, 5, 5, 5, 5]);
auto g7 = a7.group;
static assert(is(typeof(g7) : SortedRange!TT, TT));
assert(equal(g7, [tuple(1, 2u), tuple(2, 1u), tuple(5, 4u)]));
}

// Used by implementation of chunkBy for non-forward input ranges.
Expand Down