Fix Issue 8341 - topN(zip()) doesn't work

This commit is contained in:
Sebastian Wilzbach 2018-02-11 00:51:15 +01:00
parent fcaf801cd1
commit ede44cbc63
2 changed files with 27 additions and 15 deletions

View file

@ -84,11 +84,6 @@ import std.typecons; // : tuple, Tuple;
// bringToFront // bringToFront
/** /**
The `bringToFront` function has considerable flexibility and
usefulness. It can rotate elements in one buffer left or right, swap
buffers of equal length, and even move elements across disjoint
buffers of different types and different lengths.
`bringToFront` takes two ranges `front` and `back`, which may `bringToFront` takes two ranges `front` and `back`, which may
be of different types. Considering the concatenation of `front` and be of different types. Considering the concatenation of `front` and
`back` one unified range, `bringToFront` rotates that unified `back` one unified range, `bringToFront` rotates that unified
@ -104,6 +99,10 @@ in ranges, not as a string function.
Performs $(BIGOH max(front.length, back.length)) evaluations of $(D Performs $(BIGOH max(front.length, back.length)) evaluations of $(D
swap). swap).
The `bringToFront` function can rotate elements in one buffer left or right, swap
buffers of equal length, and even move elements across disjoint
buffers of different types and different lengths.
Preconditions: Preconditions:
Either `front` and `back` are disjoint, or `back` is Either `front` and `back` are disjoint, or `back` is

View file

@ -112,8 +112,9 @@ Params:
sorted. sorted.
*/ */
void completeSort(alias less = "a < b", SwapStrategy ss = SwapStrategy.unstable, void completeSort(alias less = "a < b", SwapStrategy ss = SwapStrategy.unstable,
RandomAccessRange1, RandomAccessRange2)(SortedRange!(RandomAccessRange1, less) lhs, RandomAccessRange2 rhs) Lhs , Rhs)(SortedRange!(Lhs, less) lhs, Rhs rhs)
if (hasLength!(RandomAccessRange2) && hasSlicing!(RandomAccessRange2)) if (hasLength!(Rhs) && hasSlicing!(Rhs)
&& hasSwappableElements!Lhs && hasSwappableElements!Rhs)
{ {
import std.algorithm.mutation : bringToFront; import std.algorithm.mutation : bringToFront;
import std.range : chain, assumeSorted; import std.range : chain, assumeSorted;
@ -393,7 +394,8 @@ the relative ordering of all elements `a`, `b` in the left part of `r`
for which `predicate(a) == predicate(b)`. for which `predicate(a) == predicate(b)`.
*/ */
Range partition(alias predicate, SwapStrategy ss, Range)(Range r) Range partition(alias predicate, SwapStrategy ss, Range)(Range r)
if (ss == SwapStrategy.stable && isRandomAccessRange!(Range) && hasLength!Range && hasSlicing!Range) if (ss == SwapStrategy.stable && isRandomAccessRange!(Range) && hasLength!Range &&
hasSlicing!Range && hasSwappableElements!Range)
{ {
import std.algorithm.mutation : bringToFront; import std.algorithm.mutation : bringToFront;
@ -611,7 +613,7 @@ Keynote), Andrei Alexandrescu.
*/ */
size_t pivotPartition(alias less = "a < b", Range) size_t pivotPartition(alias less = "a < b", Range)
(Range r, size_t pivot) (Range r, size_t pivot)
if (isRandomAccessRange!Range && hasLength!Range && hasSlicing!Range) if (isRandomAccessRange!Range && hasLength!Range && hasSlicing!Range && hasAssignableElements!Range)
{ {
assert(pivot < r.length || r.length == 0 && pivot == 0); assert(pivot < r.length || r.length == 0 && pivot == 0);
if (r.length <= 1) return 0; if (r.length <= 1) return 0;
@ -631,7 +633,7 @@ if (isRandomAccessRange!Range && hasLength!Range && hasSlicing!Range)
auto p = r[0]; auto p = r[0];
// Plant the pivot in the end as well as a sentinel // Plant the pivot in the end as well as a sentinel
size_t lo = 0, hi = r.length - 1; size_t lo = 0, hi = r.length - 1;
auto save = move(r[hi]); auto save = r.moveAt(hi);
r[hi] = p; // Vacancy is in r[$ - 1] now r[hi] = p; // Vacancy is in r[$ - 1] now
// Start process // Start process
for (;;) for (;;)
@ -956,7 +958,7 @@ makeIndex(
RangeIndex) RangeIndex)
(Range r, RangeIndex index) (Range r, RangeIndex index)
if (isForwardRange!(Range) && isRandomAccessRange!(RangeIndex) if (isForwardRange!(Range) && isRandomAccessRange!(RangeIndex)
&& is(ElementType!(RangeIndex) : ElementType!(Range)*)) && is(ElementType!(RangeIndex) : ElementType!(Range)*) && hasAssignableElements!RangeIndex)
{ {
import std.algorithm.internal : addressOf; import std.algorithm.internal : addressOf;
import std.exception : enforce; import std.exception : enforce;
@ -980,7 +982,7 @@ void makeIndex(
(Range r, RangeIndex index) (Range r, RangeIndex index)
if (isRandomAccessRange!Range && !isInfinite!Range && if (isRandomAccessRange!Range && !isInfinite!Range &&
isRandomAccessRange!RangeIndex && !isInfinite!RangeIndex && isRandomAccessRange!RangeIndex && !isInfinite!RangeIndex &&
isIntegral!(ElementType!RangeIndex)) isIntegral!(ElementType!RangeIndex) && hasAssignableElements!RangeIndex)
{ {
import std.conv : to; import std.conv : to;
import std.exception : enforce; import std.exception : enforce;
@ -1450,7 +1452,7 @@ Returns:
template multiSort(less...) //if (less.length > 1) template multiSort(less...) //if (less.length > 1)
{ {
auto multiSort(Range)(Range r) auto multiSort(Range)(Range r)
if (validPredicates!(ElementType!Range, less)) if (validPredicates!(ElementType!Range, less) && hasSwappableElements!Range)
{ {
import std.meta : AliasSeq; import std.meta : AliasSeq;
import std.range : assumeSorted; import std.range : assumeSorted;
@ -2900,7 +2902,7 @@ SortedRange!(R, ((a, b) => binaryFun!less(unaryFun!transform(a),
unaryFun!transform(b)))) unaryFun!transform(b))))
schwartzSort(alias transform, alias less = "a < b", schwartzSort(alias transform, alias less = "a < b",
SwapStrategy ss = SwapStrategy.unstable, R)(R r) SwapStrategy ss = SwapStrategy.unstable, R)(R r)
if (isRandomAccessRange!R && hasLength!R) if (isRandomAccessRange!R && hasLength!R && hasSwappableElements!R)
{ {
import std.conv : emplace; import std.conv : emplace;
import std.range : zip, SortedRange; import std.range : zip, SortedRange;
@ -3100,7 +3102,8 @@ Stable topN has not been implemented yet.
auto topN(alias less = "a < b", auto topN(alias less = "a < b",
SwapStrategy ss = SwapStrategy.unstable, SwapStrategy ss = SwapStrategy.unstable,
Range)(Range r, size_t nth) Range)(Range r, size_t nth)
if (isRandomAccessRange!(Range) && hasLength!Range && hasSlicing!Range) if (isRandomAccessRange!(Range) && hasLength!Range &&
hasSlicing!Range && hasAssignableElements!Range)
{ {
static assert(ss == SwapStrategy.unstable, static assert(ss == SwapStrategy.unstable,
"Stable topN not yet implemented"); "Stable topN not yet implemented");
@ -3133,6 +3136,16 @@ if (isRandomAccessRange!(Range) && hasLength!Range && hasSlicing!Range)
assert(v[n] == 9); assert(v[n] == 9);
} }
// https://issues.dlang.org/show_bug.cgi?id=8341
unittest
{
import std.algorithm.comparison : equal;
import std.typecons : tuple;
auto a = [10, 30, 20];
auto b = ["c", "b", "a"];
assert(topN!"a[0] > b[0]"(zip(a, b), 2).equal([tuple(20, "a"), tuple(30, "b")]));
}
private @trusted private @trusted
void topNImpl(alias less, R)(R r, size_t n, ref bool useSampling) void topNImpl(alias less, R)(R r, size_t n, ref bool useSampling)
{ {