]> git.ipfire.org Git - thirdparty/gcc.git/blame - libphobos/src/std/algorithm/searching.d
ipa-param-manip: Be careful about a reallocating hash_map
[thirdparty/gcc.git] / libphobos / src / std / algorithm / searching.d
CommitLineData
b4c522fa
IB
1// Written in the D programming language.
2/**
3This is a submodule of $(MREF std, algorithm).
4It contains generic _searching algorithms.
5
6$(SCRIPT inhibitQuickIndex = 1;)
7$(BOOKTABLE Cheat Sheet,
8$(TR $(TH Function Name) $(TH Description))
9$(T2 all,
10 $(D all!"a > 0"([1, 2, 3, 4])) returns $(D true) because all elements
11 are positive)
12$(T2 any,
13 $(D any!"a > 0"([1, 2, -3, -4])) returns $(D true) because at least one
14 element is positive)
15$(T2 balancedParens,
16 $(D balancedParens("((1 + 1) / 2)")) returns $(D true) because the
17 string has balanced parentheses.)
18$(T2 boyerMooreFinder,
19 $(D find("hello world", boyerMooreFinder("or"))) returns $(D "orld")
20 using the $(LINK2 https://en.wikipedia.org/wiki/Boyer%E2%80%93Moore_string_search_algorithm,
21 Boyer-Moore _algorithm).)
22$(T2 canFind,
23 $(D canFind("hello world", "or")) returns $(D true).)
24$(T2 count,
25 Counts elements that are equal to a specified value or satisfy a
26 predicate. $(D count([1, 2, 1], 1)) returns $(D 2) and
27 $(D count!"a < 0"([1, -3, 0])) returns $(D 1).)
28$(T2 countUntil,
29 $(D countUntil(a, b)) returns the number of steps taken in $(D a) to
30 reach $(D b); for example, $(D countUntil("hello!", "o")) returns
31 $(D 4).)
32$(T2 commonPrefix,
33 $(D commonPrefix("parakeet", "parachute")) returns $(D "para").)
34$(T2 endsWith,
35 $(D endsWith("rocks", "ks")) returns $(D true).)
36$(T2 find,
37 $(D find("hello world", "or")) returns $(D "orld") using linear search.
38 (For binary search refer to $(REF sortedRange, std,range).))
39$(T2 findAdjacent,
40 $(D findAdjacent([1, 2, 3, 3, 4])) returns the subrange starting with
41 two equal adjacent elements, i.e. $(D [3, 3, 4]).)
42$(T2 findAmong,
43 $(D findAmong("abcd", "qcx")) returns $(D "cd") because $(D 'c') is
44 among $(D "qcx").)
45$(T2 findSkip,
46 If $(D a = "abcde"), then $(D findSkip(a, "x")) returns $(D false) and
47 leaves $(D a) unchanged, whereas $(D findSkip(a, "c")) advances $(D a)
48 to $(D "de") and returns $(D true).)
49$(T2 findSplit,
50 $(D findSplit("abcdefg", "de")) returns the three ranges $(D "abc"),
51 $(D "de"), and $(D "fg").)
52$(T2 findSplitAfter,
53 $(D findSplitAfter("abcdefg", "de")) returns the two ranges
54 $(D "abcde") and $(D "fg").)
55$(T2 findSplitBefore,
56 $(D findSplitBefore("abcdefg", "de")) returns the two ranges $(D "abc")
57 and $(D "defg").)
58$(T2 minCount,
59 $(D minCount([2, 1, 1, 4, 1])) returns $(D tuple(1, 3)).)
60$(T2 maxCount,
61 $(D maxCount([2, 4, 1, 4, 1])) returns $(D tuple(4, 2)).)
62$(T2 minElement,
63 Selects the minimal element of a range.
64 `minElement([3, 4, 1, 2])` returns `1`.)
65$(T2 maxElement,
66 Selects the maximal element of a range.
67 `maxElement([3, 4, 1, 2])` returns `4`.)
68$(T2 minIndex,
69 Index of the minimal element of a range.
70 `minElement([3, 4, 1, 2])` returns `2`.)
71$(T2 maxIndex,
72 Index of the maximal element of a range.
73 `maxElement([3, 4, 1, 2])` returns `1`.)
74$(T2 minPos,
75 $(D minPos([2, 3, 1, 3, 4, 1])) returns the subrange $(D [1, 3, 4, 1]),
76 i.e., positions the range at the first occurrence of its minimal
77 element.)
78$(T2 maxPos,
79 $(D maxPos([2, 3, 1, 3, 4, 1])) returns the subrange $(D [4, 1]),
80 i.e., positions the range at the first occurrence of its maximal
81 element.)
82$(T2 mismatch,
83 $(D mismatch("parakeet", "parachute")) returns the two ranges
84 $(D "keet") and $(D "chute").)
85$(T2 skipOver,
86 Assume $(D a = "blah"). Then $(D skipOver(a, "bi")) leaves $(D a)
87 unchanged and returns $(D false), whereas $(D skipOver(a, "bl"))
88 advances $(D a) to refer to $(D "ah") and returns $(D true).)
89$(T2 startsWith,
90 $(D startsWith("hello, world", "hello")) returns $(D true).)
91$(T2 until,
92 Lazily iterates a range until a specific value is found.)
93)
94
95Copyright: Andrei Alexandrescu 2008-.
96
97License: $(HTTP boost.org/LICENSE_1_0.txt, Boost License 1.0).
98
99Authors: $(HTTP erdani.com, Andrei Alexandrescu)
100
101Source: $(PHOBOSSRC std/algorithm/_searching.d)
102
103Macros:
104T2=$(TR $(TDNW $(LREF $1)) $(TD $+))
105 */
106module std.algorithm.searching;
107
108// FIXME
109import std.functional; // : unaryFun, binaryFun;
110import std.range.primitives;
111import std.traits;
112// FIXME
113import std.typecons; // : Tuple, Flag, Yes, No;
114
115/++
116Checks if $(I _all) of the elements verify $(D pred).
117 +/
118template all(alias pred = "a")
119{
120 /++
121 Returns $(D true) if and only if $(I _all) values $(D v) found in the
122 input _range $(D range) satisfy the predicate $(D pred).
123 Performs (at most) $(BIGOH range.length) evaluations of $(D pred).
124 +/
125 bool all(Range)(Range range)
126 if (isInputRange!Range && is(typeof(unaryFun!pred(range.front))))
127 {
128 import std.functional : not;
129
130 return find!(not!(unaryFun!pred))(range).empty;
131 }
132}
133
134///
135@safe unittest
136{
137 assert( all!"a & 1"([1, 3, 5, 7, 9]));
138 assert(!all!"a & 1"([1, 2, 3, 5, 7, 9]));
139}
140
141/++
142$(D all) can also be used without a predicate, if its items can be
143evaluated to true or false in a conditional statement. This can be a
144convenient way to quickly evaluate that $(I _all) of the elements of a range
145are true.
146 +/
147@safe unittest
148{
149 int[3] vals = [5, 3, 18];
150 assert( all(vals[]));
151}
152
153@safe unittest
154{
155 int x = 1;
156 assert(all!(a => a > x)([2, 3]));
157}
158
159/++
160Checks if $(I _any) of the elements verifies $(D pred).
161$(D !any) can be used to verify that $(I none) of the elements verify
162$(D pred).
163This is sometimes called `exists` in other languages.
164 +/
165template any(alias pred = "a")
166{
167 /++
168 Returns $(D true) if and only if $(I _any) value $(D v) found in the
169 input _range $(D range) satisfies the predicate $(D pred).
170 Performs (at most) $(BIGOH range.length) evaluations of $(D pred).
171 +/
172 bool any(Range)(Range range)
173 if (isInputRange!Range && is(typeof(unaryFun!pred(range.front))))
174 {
175 return !find!pred(range).empty;
176 }
177}
178
179///
180@safe unittest
181{
182 import std.ascii : isWhite;
183 assert( all!(any!isWhite)(["a a", "b b"]));
184 assert(!any!(all!isWhite)(["a a", "b b"]));
185}
186
187/++
188$(D any) can also be used without a predicate, if its items can be
189evaluated to true or false in a conditional statement. $(D !any) can be a
190convenient way to quickly test that $(I none) of the elements of a range
191evaluate to true.
192 +/
193@safe unittest
194{
195 int[3] vals1 = [0, 0, 0];
196 assert(!any(vals1[])); //none of vals1 evaluate to true
197
198 int[3] vals2 = [2, 0, 2];
199 assert( any(vals2[]));
200 assert(!all(vals2[]));
201
202 int[3] vals3 = [3, 3, 3];
203 assert( any(vals3[]));
204 assert( all(vals3[]));
205}
206
207@safe unittest
208{
209 auto a = [ 1, 2, 0, 4 ];
210 assert(any!"a == 2"(a));
211}
212
213// balancedParens
214/**
215Checks whether $(D r) has "balanced parentheses", i.e. all instances
216of $(D lPar) are closed by corresponding instances of $(D rPar). The
217parameter $(D maxNestingLevel) controls the nesting level allowed. The
218most common uses are the default or $(D 0). In the latter case, no
219nesting is allowed.
220
221Params:
222 r = The range to check.
223 lPar = The element corresponding with a left (opening) parenthesis.
224 rPar = The element corresponding with a right (closing) parenthesis.
225 maxNestingLevel = The maximum allowed nesting level.
226
227Returns:
228 true if the given range has balanced parenthesis within the given maximum
229 nesting level; false otherwise.
230*/
231bool balancedParens(Range, E)(Range r, E lPar, E rPar,
232 size_t maxNestingLevel = size_t.max)
233if (isInputRange!(Range) && is(typeof(r.front == lPar)))
234{
235 size_t count;
236 for (; !r.empty; r.popFront())
237 {
238 if (r.front == lPar)
239 {
240 if (count > maxNestingLevel) return false;
241 ++count;
242 }
243 else if (r.front == rPar)
244 {
245 if (!count) return false;
246 --count;
247 }
248 }
249 return count == 0;
250}
251
252///
253@safe unittest
254{
255 auto s = "1 + (2 * (3 + 1 / 2)";
256 assert(!balancedParens(s, '(', ')'));
257 s = "1 + (2 * (3 + 1) / 2)";
258 assert(balancedParens(s, '(', ')'));
259 s = "1 + (2 * (3 + 1) / 2)";
260 assert(!balancedParens(s, '(', ')', 0));
261 s = "1 + (2 * 3 + 1) / (2 - 5)";
262 assert(balancedParens(s, '(', ')', 0));
263}
264
265/**
266 * Sets up Boyer-Moore matching for use with $(D find) below.
267 * By default, elements are compared for equality.
268 *
269 * $(D BoyerMooreFinder) allocates GC memory.
270 *
271 * Params:
272 * pred = Predicate used to compare elements.
273 * needle = A random-access range with length and slicing.
274 *
275 * Returns:
276 * An instance of $(D BoyerMooreFinder) that can be used with $(D find()) to
277 * invoke the Boyer-Moore matching algorithm for finding of $(D needle) in a
278 * given haystack.
279 */
280struct BoyerMooreFinder(alias pred, Range)
281{
282private:
283 size_t[] skip; // GC allocated
284 ptrdiff_t[ElementType!(Range)] occ; // GC allocated
285 Range needle;
286
287 ptrdiff_t occurrence(ElementType!(Range) c)
288 {
289 auto p = c in occ;
290 return p ? *p : -1;
291 }
292
293/*
294This helper function checks whether the last "portion" bytes of
295"needle" (which is "nlen" bytes long) exist within the "needle" at
296offset "offset" (counted from the end of the string), and whether the
297character preceding "offset" is not a match. Notice that the range
298being checked may reach beyond the beginning of the string. Such range
299is ignored.
300 */
301 static bool needlematch(R)(R needle,
302 size_t portion, size_t offset)
303 {
304 import std.algorithm.comparison : equal;
305 ptrdiff_t virtual_begin = needle.length - offset - portion;
306 ptrdiff_t ignore = 0;
307 if (virtual_begin < 0)
308 {
309 ignore = -virtual_begin;
310 virtual_begin = 0;
311 }
312 if (virtual_begin > 0
313 && needle[virtual_begin - 1] == needle[$ - portion - 1])
314 return 0;
315
316 immutable delta = portion - ignore;
317 return equal(needle[needle.length - delta .. needle.length],
318 needle[virtual_begin .. virtual_begin + delta]);
319 }
320
321public:
322 ///
323 this(Range needle)
324 {
325 if (!needle.length) return;
326 this.needle = needle;
327 /* Populate table with the analysis of the needle */
328 /* But ignoring the last letter */
329 foreach (i, n ; needle[0 .. $ - 1])
330 {
331 this.occ[n] = i;
332 }
333 /* Preprocess #2: init skip[] */
334 /* Note: This step could be made a lot faster.
335 * A simple implementation is shown here. */
336 this.skip = new size_t[needle.length];
337 foreach (a; 0 .. needle.length)
338 {
339 size_t value = 0;
340 while (value < needle.length
341 && !needlematch(needle, a, value))
342 {
343 ++value;
344 }
345 this.skip[needle.length - a - 1] = value;
346 }
347 }
348
349 ///
350 Range beFound(Range haystack)
351 {
352 import std.algorithm.comparison : max;
353
354 if (!needle.length) return haystack;
355 if (needle.length > haystack.length) return haystack[$ .. $];
356 /* Search: */
357 immutable limit = haystack.length - needle.length;
358 for (size_t hpos = 0; hpos <= limit; )
359 {
360 size_t npos = needle.length - 1;
361 while (pred(needle[npos], haystack[npos+hpos]))
362 {
363 if (npos == 0) return haystack[hpos .. $];
364 --npos;
365 }
366 hpos += max(skip[npos], cast(sizediff_t) npos - occurrence(haystack[npos+hpos]));
367 }
368 return haystack[$ .. $];
369 }
370
371 ///
372 @property size_t length()
373 {
374 return needle.length;
375 }
376
377 ///
378 alias opDollar = length;
379}
380
381/// Ditto
382BoyerMooreFinder!(binaryFun!(pred), Range) boyerMooreFinder
383(alias pred = "a == b", Range)
384(Range needle)
385if ((isRandomAccessRange!(Range) && hasSlicing!Range) || isSomeString!Range)
386{
387 return typeof(return)(needle);
388}
389
390///
391@safe pure nothrow unittest
392{
393 auto bmFinder = boyerMooreFinder("TG");
394
395 string r = "TAGTGCCTGA";
396 // search for the first match in the haystack r
397 r = bmFinder.beFound(r);
398 assert(r == "TGCCTGA");
399
400 // continue search in haystack
401 r = bmFinder.beFound(r[2 .. $]);
402 assert(r == "TGA");
403}
404
405/**
406Returns the common prefix of two ranges.
407
408Params:
409 pred = The predicate to use in comparing elements for commonality. Defaults
410 to equality $(D "a == b").
411
412 r1 = A $(REF_ALTTEXT forward range, isForwardRange, std,range,primitives) of
413 elements.
414
415 r2 = An $(REF_ALTTEXT input range, isInputRange, std,range,primitives) of
416 elements.
417
418Returns:
419A slice of $(D r1) which contains the characters that both ranges start with,
420if the first argument is a string; otherwise, the same as the result of
421$(D takeExactly(r1, n)), where $(D n) is the number of elements in the common
422prefix of both ranges.
423
424See_Also:
425 $(REF takeExactly, std,range)
426 */
427auto commonPrefix(alias pred = "a == b", R1, R2)(R1 r1, R2 r2)
428if (isForwardRange!R1 && isInputRange!R2 &&
429 !isNarrowString!R1 &&
430 is(typeof(binaryFun!pred(r1.front, r2.front))))
431{
432 import std.algorithm.comparison : min;
433 static if (isRandomAccessRange!R1 && isRandomAccessRange!R2 &&
434 hasLength!R1 && hasLength!R2 &&
435 hasSlicing!R1)
436 {
437 immutable limit = min(r1.length, r2.length);
438 foreach (i; 0 .. limit)
439 {
440 if (!binaryFun!pred(r1[i], r2[i]))
441 {
442 return r1[0 .. i];
443 }
444 }
445 return r1[0 .. limit];
446 }
447 else
448 {
449 import std.range : takeExactly;
450 auto result = r1.save;
451 size_t i = 0;
452 for (;
453 !r1.empty && !r2.empty && binaryFun!pred(r1.front, r2.front);
454 ++i, r1.popFront(), r2.popFront())
455 {}
456 return takeExactly(result, i);
457 }
458}
459
460///
461@safe unittest
462{
463 assert(commonPrefix("hello, world", "hello, there") == "hello, ");
464}
465
466/// ditto
467auto commonPrefix(alias pred, R1, R2)(R1 r1, R2 r2)
468if (isNarrowString!R1 && isInputRange!R2 &&
469 is(typeof(binaryFun!pred(r1.front, r2.front))))
470{
471 import std.utf : decode;
472
473 auto result = r1.save;
474 immutable len = r1.length;
475 size_t i = 0;
476
477 for (size_t j = 0; i < len && !r2.empty; r2.popFront(), i = j)
478 {
479 immutable f = decode(r1, j);
480 if (!binaryFun!pred(f, r2.front))
481 break;
482 }
483
484 return result[0 .. i];
485}
486
487/// ditto
488auto commonPrefix(R1, R2)(R1 r1, R2 r2)
489if (isNarrowString!R1 && isInputRange!R2 && !isNarrowString!R2 &&
490 is(typeof(r1.front == r2.front)))
491{
492 return commonPrefix!"a == b"(r1, r2);
493}
494
495/// ditto
496auto commonPrefix(R1, R2)(R1 r1, R2 r2)
497if (isNarrowString!R1 && isNarrowString!R2)
498{
499 import std.algorithm.comparison : min;
500
501 static if (ElementEncodingType!R1.sizeof == ElementEncodingType!R2.sizeof)
502 {
503 import std.utf : stride, UTFException;
504
505 immutable limit = min(r1.length, r2.length);
506 for (size_t i = 0; i < limit;)
507 {
508 immutable codeLen = stride(r1, i);
509 size_t j = 0;
510
511 for (; j < codeLen && i < limit; ++i, ++j)
512 {
513 if (r1[i] != r2[i])
514 return r1[0 .. i - j];
515 }
516
517 if (i == limit && j < codeLen)
518 throw new UTFException("Invalid UTF-8 sequence", i);
519 }
520 return r1[0 .. limit];
521 }
522 else
523 return commonPrefix!"a == b"(r1, r2);
524}
525
526@safe unittest
527{
528 import std.algorithm.comparison : equal;
529 import std.algorithm.iteration : filter;
530 import std.conv : to;
531 import std.exception : assertThrown;
532 import std.meta : AliasSeq;
533 import std.range;
534 import std.utf : UTFException;
535
536 assert(commonPrefix([1, 2, 3], [1, 2, 3, 4, 5]) == [1, 2, 3]);
537 assert(commonPrefix([1, 2, 3, 4, 5], [1, 2, 3]) == [1, 2, 3]);
538 assert(commonPrefix([1, 2, 3, 4], [1, 2, 3, 4]) == [1, 2, 3, 4]);
539 assert(commonPrefix([1, 2, 3], [7, 2, 3, 4, 5]).empty);
540 assert(commonPrefix([7, 2, 3, 4, 5], [1, 2, 3]).empty);
541 assert(commonPrefix([1, 2, 3], cast(int[]) null).empty);
542 assert(commonPrefix(cast(int[]) null, [1, 2, 3]).empty);
543 assert(commonPrefix(cast(int[]) null, cast(int[]) null).empty);
544
545 foreach (S; AliasSeq!(char[], const(char)[], string,
546 wchar[], const(wchar)[], wstring,
547 dchar[], const(dchar)[], dstring))
548 {
549 foreach (T; AliasSeq!(string, wstring, dstring))
550 (){ // avoid slow optimizations for large functions @@@BUG@@@ 2396
551 assert(commonPrefix(to!S(""), to!T("")).empty);
552 assert(commonPrefix(to!S(""), to!T("hello")).empty);
553 assert(commonPrefix(to!S("hello"), to!T("")).empty);
554 assert(commonPrefix(to!S("hello, world"), to!T("hello, there")) == to!S("hello, "));
555 assert(commonPrefix(to!S("hello, there"), to!T("hello, world")) == to!S("hello, "));
556 assert(commonPrefix(to!S("hello, "), to!T("hello, world")) == to!S("hello, "));
557 assert(commonPrefix(to!S("hello, world"), to!T("hello, ")) == to!S("hello, "));
558 assert(commonPrefix(to!S("hello, world"), to!T("hello, world")) == to!S("hello, world"));
559
560 //Bug# 8890
561 assert(commonPrefix(to!S("Пиво"), to!T("Пони"))== to!S("П"));
562 assert(commonPrefix(to!S("Пони"), to!T("Пиво"))== to!S("П"));
563 assert(commonPrefix(to!S("Пиво"), to!T("Пиво"))== to!S("Пиво"));
564 assert(commonPrefix(to!S("\U0010FFFF\U0010FFFB\U0010FFFE"),
565 to!T("\U0010FFFF\U0010FFFB\U0010FFFC")) == to!S("\U0010FFFF\U0010FFFB"));
566 assert(commonPrefix(to!S("\U0010FFFF\U0010FFFB\U0010FFFC"),
567 to!T("\U0010FFFF\U0010FFFB\U0010FFFE")) == to!S("\U0010FFFF\U0010FFFB"));
568 assert(commonPrefix!"a != b"(to!S("Пиво"), to!T("онво")) == to!S("Пи"));
569 assert(commonPrefix!"a != b"(to!S("онво"), to!T("Пиво")) == to!S("он"));
570 }();
571
572 static assert(is(typeof(commonPrefix(to!S("Пиво"), filter!"true"("Пони"))) == S));
573 assert(equal(commonPrefix(to!S("Пиво"), filter!"true"("Пони")), to!S("П")));
574
575 static assert(is(typeof(commonPrefix(filter!"true"("Пиво"), to!S("Пони"))) ==
576 typeof(takeExactly(filter!"true"("П"), 1))));
577 assert(equal(commonPrefix(filter!"true"("Пиво"), to!S("Пони")), takeExactly(filter!"true"("П"), 1)));
578 }
579
580 assertThrown!UTFException(commonPrefix("\U0010FFFF\U0010FFFB", "\U0010FFFF\U0010FFFB"[0 .. $ - 1]));
581
582 assert(commonPrefix("12345"d, [49, 50, 51, 60, 60]) == "123"d);
583 assert(commonPrefix([49, 50, 51, 60, 60], "12345" ) == [49, 50, 51]);
584 assert(commonPrefix([49, 50, 51, 60, 60], "12345"d) == [49, 50, 51]);
585
586 assert(commonPrefix!"a == ('0' + b)"("12345" , [1, 2, 3, 9, 9]) == "123");
587 assert(commonPrefix!"a == ('0' + b)"("12345"d, [1, 2, 3, 9, 9]) == "123"d);
588 assert(commonPrefix!"('0' + a) == b"([1, 2, 3, 9, 9], "12345" ) == [1, 2, 3]);
589 assert(commonPrefix!"('0' + a) == b"([1, 2, 3, 9, 9], "12345"d) == [1, 2, 3]);
590}
591
592// count
593/**
594The first version counts the number of elements $(D x) in $(D r) for
595which $(D pred(x, value)) is $(D true). $(D pred) defaults to
596equality. Performs $(BIGOH haystack.length) evaluations of $(D pred).
597
598The second version returns the number of times $(D needle) occurs in
599$(D haystack). Throws an exception if $(D needle.empty), as the _count
600of the empty range in any range would be infinite. Overlapped counts
601are not considered, for example $(D count("aaa", "aa")) is $(D 1), not
602$(D 2).
603
604The third version counts the elements for which $(D pred(x)) is $(D
605true). Performs $(BIGOH haystack.length) evaluations of $(D pred).
606
607The fourth version counts the number of elements in a range. It is
608an optimization for the third version: if the given range has the
609`length` property the count is returned right away, otherwise
610performs $(BIGOH haystack.length) to walk the range.
611
612Note: Regardless of the overload, $(D count) will not accept
613infinite ranges for $(D haystack).
614
615Params:
616 pred = The predicate to evaluate.
617 haystack = The range to _count.
618 needle = The element or sub-range to _count in the `haystack`.
619
620Returns:
621 The number of positions in the `haystack` for which `pred` returned true.
622*/
623size_t count(alias pred = "a == b", Range, E)(Range haystack, E needle)
624if (isInputRange!Range && !isInfinite!Range &&
625 is(typeof(binaryFun!pred(haystack.front, needle)) : bool))
626{
627 bool pred2(ElementType!Range a) { return binaryFun!pred(a, needle); }
628 return count!pred2(haystack);
629}
630
631///
632@safe unittest
633{
634 import std.uni : toLower;
635
636 // count elements in range
637 int[] a = [ 1, 2, 4, 3, 2, 5, 3, 2, 4 ];
638 assert(count(a) == 9);
639 assert(count(a, 2) == 3);
640 assert(count!("a > b")(a, 2) == 5);
641 // count range in range
642 assert(count("abcadfabf", "ab") == 2);
643 assert(count("ababab", "abab") == 1);
644 assert(count("ababab", "abx") == 0);
645 // fuzzy count range in range
646 assert(count!((a, b) => toLower(a) == toLower(b))("AbcAdFaBf", "ab") == 2);
647 // count predicate in range
648 assert(count!("a > 1")(a) == 8);
649}
650
651@safe unittest
652{
653 import std.conv : text;
654
655 int[] a = [ 1, 2, 4, 3, 2, 5, 3, 2, 4 ];
656 assert(count(a, 2) == 3, text(count(a, 2)));
657 assert(count!("a > b")(a, 2) == 5, text(count!("a > b")(a, 2)));
658
659 // check strings
660 assert(count("日本語") == 3);
661 assert(count("日本語"w) == 3);
662 assert(count("日本語"d) == 3);
663
664 assert(count!("a == '日'")("日本語") == 1);
665 assert(count!("a == '本'")("日本語"w) == 1);
666 assert(count!("a == '語'")("日本語"d) == 1);
667}
668
669@safe unittest
670{
671 string s = "This is a fofofof list";
672 string sub = "fof";
673 assert(count(s, sub) == 2);
674}
675
676/// Ditto
677size_t count(alias pred = "a == b", R1, R2)(R1 haystack, R2 needle)
678if (isForwardRange!R1 && !isInfinite!R1 &&
679 isForwardRange!R2 &&
680 is(typeof(binaryFun!pred(haystack.front, needle.front)) : bool))
681{
682 assert(!needle.empty, "Cannot count occurrences of an empty range");
683
684 static if (isInfinite!R2)
685 {
686 //Note: This is the special case of looking for an infinite inside a finite...
687 //"How many instances of the Fibonacci sequence can you count in [1, 2, 3]?" - "None."
688 return 0;
689 }
690 else
691 {
692 size_t result;
693 //Note: haystack is not saved, because findskip is designed to modify it
694 for ( ; findSkip!pred(haystack, needle.save) ; ++result)
695 {}
696 return result;
697 }
698}
699
700/// Ditto
701size_t count(alias pred, R)(R haystack)
702if (isInputRange!R && !isInfinite!R &&
703 is(typeof(unaryFun!pred(haystack.front)) : bool))
704{
705 size_t result;
706 alias T = ElementType!R; //For narrow strings forces dchar iteration
707 foreach (T elem; haystack)
708 if (unaryFun!pred(elem)) ++result;
709 return result;
710}
711
712/// Ditto
713size_t count(R)(R haystack)
714if (isInputRange!R && !isInfinite!R)
715{
716 return walkLength(haystack);
717}
718
719@safe unittest
720{
721 int[] a = [ 1, 2, 4, 3, 2, 5, 3, 2, 4 ];
722 assert(count!("a == 3")(a) == 2);
723 assert(count("日本語") == 3);
724}
725
726// Issue 11253
727@safe nothrow unittest
728{
729 assert([1, 2, 3].count([2, 3]) == 1);
730}
731
732/++
733 Counts elements in the given
734 $(REF_ALTTEXT forward range, isForwardRange, std,range,primitives)
735 until the given predicate is true for one of the given $(D needles).
736
737 Params:
738 pred = The predicate for determining when to stop counting.
739 haystack = The
740 $(REF_ALTTEXT input range, isInputRange, std,range,primitives) to be
741 counted.
742 needles = Either a single element, or a
743 $(REF_ALTTEXT forward range, isForwardRange, std,range,primitives)
744 of elements, to be evaluated in turn against each
745 element in $(D haystack) under the given predicate.
746
747 Returns: The number of elements which must be popped from the front of
748 $(D haystack) before reaching an element for which
749 $(D startsWith!pred(haystack, needles)) is $(D true). If
750 $(D startsWith!pred(haystack, needles)) is not $(D true) for any element in
751 $(D haystack), then $(D -1) is returned.
752
753 See_Also: $(REF indexOf, std,string)
754 +/
755ptrdiff_t countUntil(alias pred = "a == b", R, Rs...)(R haystack, Rs needles)
756if (isForwardRange!R
757 && Rs.length > 0
758 && isForwardRange!(Rs[0]) == isInputRange!(Rs[0])
759 && is(typeof(startsWith!pred(haystack, needles[0])))
760 && (Rs.length == 1
761 || is(typeof(countUntil!pred(haystack, needles[1 .. $])))))
762{
763 typeof(return) result;
764
765 static if (needles.length == 1)
766 {
767 static if (hasLength!R) //Note: Narrow strings don't have length.
768 {
769 //We delegate to find because find is very efficient.
770 //We store the length of the haystack so we don't have to save it.
771 auto len = haystack.length;
772 auto r2 = find!pred(haystack, needles[0]);
773 if (!r2.empty)
774 return cast(typeof(return)) (len - r2.length);
775 }
776 else
777 {
778 import std.range : dropOne;
779
780 if (needles[0].empty)
781 return 0;
782
783 //Default case, slower route doing startsWith iteration
784 for ( ; !haystack.empty ; ++result )
785 {
786 //We compare the first elements of the ranges here before
787 //forwarding to startsWith. This avoids making useless saves to
788 //haystack/needle if they aren't even going to be mutated anyways.
789 //It also cuts down on the amount of pops on haystack.
790 if (binaryFun!pred(haystack.front, needles[0].front))
791 {
792 //Here, we need to save the needle before popping it.
793 //haystack we pop in all paths, so we do that, and then save.
794 haystack.popFront();
795 if (startsWith!pred(haystack.save, needles[0].save.dropOne()))
796 return result;
797 }
798 else
799 haystack.popFront();
800 }
801 }
802 }
803 else
804 {
805 foreach (i, Ri; Rs)
806 {
807 static if (isForwardRange!Ri)
808 {
809 if (needles[i].empty)
810 return 0;
811 }
812 }
813 Tuple!Rs t;
814 foreach (i, Ri; Rs)
815 {
816 static if (!isForwardRange!Ri)
817 {
818 t[i] = needles[i];
819 }
820 }
821 for (; !haystack.empty ; ++result, haystack.popFront())
822 {
823 foreach (i, Ri; Rs)
824 {
825 static if (isForwardRange!Ri)
826 {
827 t[i] = needles[i].save;
828 }
829 }
830 if (startsWith!pred(haystack.save, t.expand))
831 {
832 return result;
833 }
834 }
835 }
836
837 //Because of @@@8804@@@: Avoids both "unreachable code" or "no return statement"
838 static if (isInfinite!R) assert(0);
839 else return -1;
840}
841
842/// ditto
843ptrdiff_t countUntil(alias pred = "a == b", R, N)(R haystack, N needle)
844if (isInputRange!R &&
845 is(typeof(binaryFun!pred(haystack.front, needle)) : bool))
846{
847 bool pred2(ElementType!R a) { return binaryFun!pred(a, needle); }
848 return countUntil!pred2(haystack);
849}
850
851///
852@safe unittest
853{
854 assert(countUntil("hello world", "world") == 6);
855 assert(countUntil("hello world", 'r') == 8);
856 assert(countUntil("hello world", "programming") == -1);
857 assert(countUntil("日本語", "本語") == 1);
858 assert(countUntil("日本語", '語') == 2);
859 assert(countUntil("日本語", "五") == -1);
860 assert(countUntil("日本語", '五') == -1);
861 assert(countUntil([0, 7, 12, 22, 9], [12, 22]) == 2);
862 assert(countUntil([0, 7, 12, 22, 9], 9) == 4);
863 assert(countUntil!"a > b"([0, 7, 12, 22, 9], 20) == 3);
864}
865
866@safe unittest
867{
868 import std.algorithm.iteration : filter;
869 import std.internal.test.dummyrange;
870
871 assert(countUntil("日本語", "") == 0);
872 assert(countUntil("日本語"d, "") == 0);
873
874 assert(countUntil("", "") == 0);
875 assert(countUntil("".filter!"true"(), "") == 0);
876
877 auto rf = [0, 20, 12, 22, 9].filter!"true"();
878 assert(rf.countUntil!"a > b"((int[]).init) == 0);
879 assert(rf.countUntil!"a > b"(20) == 3);
880 assert(rf.countUntil!"a > b"([20, 8]) == 3);
881 assert(rf.countUntil!"a > b"([20, 10]) == -1);
882 assert(rf.countUntil!"a > b"([20, 8, 0]) == -1);
883
884 auto r = new ReferenceForwardRange!int([0, 1, 2, 3, 4, 5, 6]);
885 auto r2 = new ReferenceForwardRange!int([3, 4]);
886 auto r3 = new ReferenceForwardRange!int([3, 5]);
887 assert(r.save.countUntil(3) == 3);
888 assert(r.save.countUntil(r2) == 3);
889 assert(r.save.countUntil(7) == -1);
890 assert(r.save.countUntil(r3) == -1);
891}
892
893@safe unittest
894{
895 assert(countUntil("hello world", "world", "asd") == 6);
896 assert(countUntil("hello world", "world", "ello") == 1);
897 assert(countUntil("hello world", "world", "") == 0);
898 assert(countUntil("hello world", "world", 'l') == 2);
899}
900
901/++
902 Similar to the previous overload of $(D countUntil), except that this one
903 evaluates only the predicate $(D pred).
904
905 Params:
906 pred = Predicate to when to stop counting.
907 haystack = An
908 $(REF_ALTTEXT input range, isInputRange, std,range,primitives) of
909 elements to be counted.
910 Returns: The number of elements which must be popped from $(D haystack)
911 before $(D pred(haystack.front)) is $(D true).
912 +/
913ptrdiff_t countUntil(alias pred, R)(R haystack)
914if (isInputRange!R &&
915 is(typeof(unaryFun!pred(haystack.front)) : bool))
916{
917 typeof(return) i;
918 static if (isRandomAccessRange!R)
919 {
920 //Optimized RA implementation. Since we want to count *and* iterate at
921 //the same time, it is more efficient this way.
922 static if (hasLength!R)
923 {
924 immutable len = cast(typeof(return)) haystack.length;
925 for ( ; i < len ; ++i )
926 if (unaryFun!pred(haystack[i])) return i;
927 }
928 else //if (isInfinite!R)
929 {
930 for ( ; ; ++i )
931 if (unaryFun!pred(haystack[i])) return i;
932 }
933 }
934 else static if (hasLength!R)
935 {
936 //For those odd ranges that have a length, but aren't RA.
937 //It is faster to quick find, and then compare the lengths
938 auto r2 = find!pred(haystack.save);
939 if (!r2.empty) return cast(typeof(return)) (haystack.length - r2.length);
940 }
941 else //Everything else
942 {
943 alias T = ElementType!R; //For narrow strings forces dchar iteration
944 foreach (T elem; haystack)
945 {
946 if (unaryFun!pred(elem)) return i;
947 ++i;
948 }
949 }
950
951 //Because of @@@8804@@@: Avoids both "unreachable code" or "no return statement"
952 static if (isInfinite!R) assert(0);
953 else return -1;
954}
955
956///
957@safe unittest
958{
959 import std.ascii : isDigit;
960 import std.uni : isWhite;
961
5a0aa603
IB
962 assert(countUntil!(isWhite)("hello world") == 5);
963 assert(countUntil!(isDigit)("hello world") == -1);
b4c522fa
IB
964 assert(countUntil!"a > 20"([0, 7, 12, 22, 9]) == 3);
965}
966
967@safe unittest
968{
969 import std.internal.test.dummyrange;
970
971 // References
972 {
973 // input
974 ReferenceInputRange!int r;
975 r = new ReferenceInputRange!int([0, 1, 2, 3, 4, 5, 6]);
976 assert(r.countUntil(3) == 3);
977 r = new ReferenceInputRange!int([0, 1, 2, 3, 4, 5, 6]);
978 assert(r.countUntil(7) == -1);
979 }
980 {
981 // forward
982 auto r = new ReferenceForwardRange!int([0, 1, 2, 3, 4, 5, 6]);
983 assert(r.save.countUntil([3, 4]) == 3);
984 assert(r.save.countUntil(3) == 3);
985 assert(r.save.countUntil([3, 7]) == -1);
986 assert(r.save.countUntil(7) == -1);
987 }
988 {
989 // infinite forward
990 auto r = new ReferenceInfiniteForwardRange!int(0);
991 assert(r.save.countUntil([3, 4]) == 3);
992 assert(r.save.countUntil(3) == 3);
993 }
994}
995
996/**
997Checks if the given range ends with (one of) the given needle(s).
998The reciprocal of $(D startsWith).
999
1000Params:
1001 pred = The predicate to use for comparing elements between the range and
1002 the needle(s).
1003
1004 doesThisEnd = The
1005 $(REF_ALTTEXT bidirectional range, isBidirectionalRange, std,range,primitives)
1006 to check.
1007
1008 withOneOfThese = The needles to check against, which may be single
1009 elements, or bidirectional ranges of elements.
1010
1011 withThis = The single element to check.
1012
1013Returns:
10140 if the needle(s) do not occur at the end of the given range;
1015otherwise the position of the matching needle, that is, 1 if the range ends
1016with $(D withOneOfThese[0]), 2 if it ends with $(D withOneOfThese[1]), and so
1017on.
1018
1019In the case when no needle parameters are given, return $(D true) iff back of
1020$(D doesThisStart) fulfils predicate $(D pred).
1021*/
1022uint endsWith(alias pred = "a == b", Range, Needles...)(Range doesThisEnd, Needles withOneOfThese)
1023if (isBidirectionalRange!Range && Needles.length > 1 &&
1024 is(typeof(.endsWith!pred(doesThisEnd, withOneOfThese[0])) : bool) &&
1025 is(typeof(.endsWith!pred(doesThisEnd, withOneOfThese[1 .. $])) : uint))
1026{
1027 alias haystack = doesThisEnd;
1028 alias needles = withOneOfThese;
1029
1030 // Make one pass looking for empty ranges in needles
1031 foreach (i, Unused; Needles)
1032 {
1033 // Empty range matches everything
1034 static if (!is(typeof(binaryFun!pred(haystack.back, needles[i])) : bool))
1035 {
1036 if (needles[i].empty) return i + 1;
1037 }
1038 }
1039
1040 for (; !haystack.empty; haystack.popBack())
1041 {
1042 foreach (i, Unused; Needles)
1043 {
1044 static if (is(typeof(binaryFun!pred(haystack.back, needles[i])) : bool))
1045 {
1046 // Single-element
1047 if (binaryFun!pred(haystack.back, needles[i]))
1048 {
1049 // found, but continue to account for one-element
1050 // range matches (consider endsWith("ab", "b",
1051 // 'b') should return 1, not 2).
1052 continue;
1053 }
1054 }
1055 else
1056 {
1057 if (binaryFun!pred(haystack.back, needles[i].back))
1058 continue;
1059 }
1060
1061 // This code executed on failure to match
1062 // Out with this guy, check for the others
1063 uint result = endsWith!pred(haystack, needles[0 .. i], needles[i + 1 .. $]);
1064 if (result > i) ++result;
1065 return result;
1066 }
1067
1068 // If execution reaches this point, then the back matches for all
1069 // needles ranges. What we need to do now is to lop off the back of
1070 // all ranges involved and recurse.
1071 foreach (i, Unused; Needles)
1072 {
1073 static if (is(typeof(binaryFun!pred(haystack.back, needles[i])) : bool))
1074 {
1075 // Test has passed in the previous loop
1076 return i + 1;
1077 }
1078 else
1079 {
1080 needles[i].popBack();
1081 if (needles[i].empty) return i + 1;
1082 }
1083 }
1084 }
1085 return 0;
1086}
1087
1088/// Ditto
1089bool endsWith(alias pred = "a == b", R1, R2)(R1 doesThisEnd, R2 withThis)
1090if (isBidirectionalRange!R1 &&
1091 isBidirectionalRange!R2 &&
1092 is(typeof(binaryFun!pred(doesThisEnd.back, withThis.back)) : bool))
1093{
1094 alias haystack = doesThisEnd;
1095 alias needle = withThis;
1096
1097 static if (is(typeof(pred) : string))
1098 enum isDefaultPred = pred == "a == b";
1099 else
1100 enum isDefaultPred = false;
1101
1102 static if (isDefaultPred && isArray!R1 && isArray!R2 &&
1103 is(Unqual!(ElementEncodingType!R1) == Unqual!(ElementEncodingType!R2)))
1104 {
1105 if (haystack.length < needle.length) return false;
1106
1107 return haystack[$ - needle.length .. $] == needle;
1108 }
1109 else
1110 {
1111 import std.range : retro;
1112 return startsWith!pred(retro(doesThisEnd), retro(withThis));
1113 }
1114}
1115
1116/// Ditto
1117bool endsWith(alias pred = "a == b", R, E)(R doesThisEnd, E withThis)
1118if (isBidirectionalRange!R &&
1119 is(typeof(binaryFun!pred(doesThisEnd.back, withThis)) : bool))
1120{
1121 if (doesThisEnd.empty)
1122 return false;
1123
1124 alias predFunc = binaryFun!pred;
1125
1126 // auto-decoding special case
1127 static if (isNarrowString!R)
1128 {
1129 // specialize for ASCII as to not change previous behavior
1130 if (withThis <= 0x7F)
1131 return predFunc(doesThisEnd[$ - 1], withThis);
1132 else
1133 return predFunc(doesThisEnd.back, withThis);
1134 }
1135 else
1136 {
1137 return predFunc(doesThisEnd.back, withThis);
1138 }
1139}
1140
1141/// Ditto
1142bool endsWith(alias pred, R)(R doesThisEnd)
1143if (isInputRange!R &&
1144 ifTestable!(typeof(doesThisEnd.front), unaryFun!pred))
1145{
1146 return !doesThisEnd.empty && unaryFun!pred(doesThisEnd.back);
1147}
1148
1149///
1150@safe unittest
1151{
1152 import std.ascii : isAlpha;
1153 assert("abc".endsWith!(a => a.isAlpha));
1154 assert("abc".endsWith!isAlpha);
1155
1156 assert(!"ab1".endsWith!(a => a.isAlpha));
1157
1158 assert(!"ab1".endsWith!isAlpha);
1159 assert(!"".endsWith!(a => a.isAlpha));
1160
1161 import std.algorithm.comparison : among;
1162 assert("abc".endsWith!(a => a.among('c', 'd') != 0));
1163 assert(!"abc".endsWith!(a => a.among('a', 'b') != 0));
1164
1165 assert(endsWith("abc", ""));
1166 assert(!endsWith("abc", "b"));
1167 assert(endsWith("abc", "a", 'c') == 2);
1168 assert(endsWith("abc", "c", "a") == 1);
1169 assert(endsWith("abc", "c", "c") == 1);
1170 assert(endsWith("abc", "bc", "c") == 2);
1171 assert(endsWith("abc", "x", "c", "b") == 2);
1172 assert(endsWith("abc", "x", "aa", "bc") == 3);
1173 assert(endsWith("abc", "x", "aaa", "sab") == 0);
1174 assert(endsWith("abc", "x", "aaa", 'c', "sab") == 3);
1175}
1176
1177@safe unittest
1178{
1179 import std.algorithm.iteration : filterBidirectional;
1180 import std.conv : to;
1181 import std.meta : AliasSeq;
1182
1183 foreach (S; AliasSeq!(char[], wchar[], dchar[], string, wstring, dstring))
1184 {
1185 assert(!endsWith(to!S("abc"), 'a'));
1186 assert(endsWith(to!S("abc"), 'a', 'c') == 2);
1187 assert(!endsWith(to!S("abc"), 'x', 'n', 'b'));
1188 assert(endsWith(to!S("abc"), 'x', 'n', 'c') == 3);
1189 assert(endsWith(to!S("abc\uFF28"), 'a', '\uFF28', 'c') == 2);
1190
1191 foreach (T; AliasSeq!(char[], wchar[], dchar[], string, wstring, dstring))
1192 (){ // avoid slow optimizations for large functions @@@BUG@@@ 2396
1193 //Lots of strings
1194 assert(endsWith(to!S("abc"), to!T("")));
1195 assert(!endsWith(to!S("abc"), to!T("a")));
1196 assert(!endsWith(to!S("abc"), to!T("b")));
1197 assert(endsWith(to!S("abc"), to!T("bc"), 'c') == 2);
1198 assert(endsWith(to!S("abc"), to!T("a"), "c") == 2);
1199 assert(endsWith(to!S("abc"), to!T("c"), "a") == 1);
1200 assert(endsWith(to!S("abc"), to!T("c"), "c") == 1);
1201 assert(endsWith(to!S("abc"), to!T("x"), 'c', "b") == 2);
1202 assert(endsWith(to!S("abc"), 'x', to!T("aa"), "bc") == 3);
1203 assert(endsWith(to!S("abc"), to!T("x"), "aaa", "sab") == 0);
1204 assert(endsWith(to!S("abc"), to!T("x"), "aaa", "c", "sab") == 3);
1205 assert(endsWith(to!S("\uFF28el\uFF4co"), to!T("l\uFF4co")));
1206 assert(endsWith(to!S("\uFF28el\uFF4co"), to!T("lo"), to!T("l\uFF4co")) == 2);
1207
1208 //Unicode
1209 assert(endsWith(to!S("\uFF28el\uFF4co"), to!T("l\uFF4co")));
1210 assert(endsWith(to!S("\uFF28el\uFF4co"), to!T("lo"), to!T("l\uFF4co")) == 2);
1211 assert(endsWith(to!S("日本語"), to!T("本語")));
1212 assert(endsWith(to!S("日本語"), to!T("日本語")));
1213 assert(!endsWith(to!S("本語"), to!T("日本語")));
1214
1215 //Empty
1216 assert(endsWith(to!S(""), T.init));
1217 assert(!endsWith(to!S(""), 'a'));
1218 assert(endsWith(to!S("a"), T.init));
1219 assert(endsWith(to!S("a"), T.init, "") == 1);
1220 assert(endsWith(to!S("a"), T.init, 'a') == 1);
1221 assert(endsWith(to!S("a"), 'a', T.init) == 2);
1222 }();
1223 }
1224
1225 foreach (T; AliasSeq!(int, short))
1226 {
1227 immutable arr = cast(T[])[0, 1, 2, 3, 4, 5];
1228
1229 //RA range
1230 assert(endsWith(arr, cast(int[]) null));
1231 assert(!endsWith(arr, 0));
1232 assert(!endsWith(arr, 4));
1233 assert(endsWith(arr, 5));
1234 assert(endsWith(arr, 0, 4, 5) == 3);
1235 assert(endsWith(arr, [5]));
1236 assert(endsWith(arr, [4, 5]));
1237 assert(endsWith(arr, [4, 5], 7) == 1);
1238 assert(!endsWith(arr, [2, 4, 5]));
1239 assert(endsWith(arr, [2, 4, 5], [3, 4, 5]) == 2);
1240
1241 //Normal input range
1242 assert(!endsWith(filterBidirectional!"true"(arr), 4));
1243 assert(endsWith(filterBidirectional!"true"(arr), 5));
1244 assert(endsWith(filterBidirectional!"true"(arr), [5]));
1245 assert(endsWith(filterBidirectional!"true"(arr), [4, 5]));
1246 assert(endsWith(filterBidirectional!"true"(arr), [4, 5], 7) == 1);
1247 assert(!endsWith(filterBidirectional!"true"(arr), [2, 4, 5]));
1248 assert(endsWith(filterBidirectional!"true"(arr), [2, 4, 5], [3, 4, 5]) == 2);
1249 assert(endsWith(arr, filterBidirectional!"true"([4, 5])));
1250 assert(endsWith(arr, filterBidirectional!"true"([4, 5]), 7) == 1);
1251 assert(!endsWith(arr, filterBidirectional!"true"([2, 4, 5])));
1252 assert(endsWith(arr, [2, 4, 5], filterBidirectional!"true"([3, 4, 5])) == 2);
1253
1254 //Non-default pred
1255 assert(endsWith!("a%10 == b%10")(arr, [14, 15]));
1256 assert(!endsWith!("a%10 == b%10")(arr, [15, 14]));
1257 }
1258}
1259
1260/**
1261Iterates the passed range and selects the extreme element with `less`.
1262If the extreme element occurs multiple time, the first occurrence will be
1263returned.
1264
1265Params:
1266 map = custom accessor for the comparison key
1267 selector = custom mapping for the extrema selection
1268 seed = custom seed to use as initial element
1269 r = Range from which the extreme value will be selected
1270
1271Returns:
1272 The extreme value according to `map` and `selector` of the passed-in values.
1273*/
1274private auto extremum(alias map, alias selector = "a < b", Range)(Range r)
1275if (isInputRange!Range && !isInfinite!Range &&
1276 is(typeof(unaryFun!map(ElementType!(Range).init))))
1277in
1278{
1279 assert(!r.empty, "r is an empty range");
1280}
1281body
1282{
1283 alias Element = ElementType!Range;
1284 Unqual!Element seed = r.front;
1285 r.popFront();
1286 return extremum!(map, selector)(r, seed);
1287}
1288
1289private auto extremum(alias map, alias selector = "a < b", Range,
1290 RangeElementType = ElementType!Range)
1291 (Range r, RangeElementType seedElement)
1292if (isInputRange!Range && !isInfinite!Range &&
1293 !is(CommonType!(ElementType!Range, RangeElementType) == void) &&
1294 is(typeof(unaryFun!map(ElementType!(Range).init))))
1295{
1296 alias mapFun = unaryFun!map;
1297 alias selectorFun = binaryFun!selector;
1298
1299 alias Element = ElementType!Range;
1300 alias CommonElement = CommonType!(Element, RangeElementType);
1301 Unqual!CommonElement extremeElement = seedElement;
1302
1303 alias MapType = Unqual!(typeof(mapFun(CommonElement.init)));
1304 MapType extremeElementMapped = mapFun(extremeElement);
1305
1306 // direct access via a random access range is faster
1307 static if (isRandomAccessRange!Range)
1308 {
1309 foreach (const i; 0 .. r.length)
1310 {
1311 MapType mapElement = mapFun(r[i]);
1312 if (selectorFun(mapElement, extremeElementMapped))
1313 {
1314 extremeElement = r[i];
1315 extremeElementMapped = mapElement;
1316 }
1317 }
1318 }
1319 else
1320 {
1321 while (!r.empty)
1322 {
1323 MapType mapElement = mapFun(r.front);
1324 if (selectorFun(mapElement, extremeElementMapped))
1325 {
1326 extremeElement = r.front;
1327 extremeElementMapped = mapElement;
1328 }
1329 r.popFront();
1330 }
1331 }
1332 return extremeElement;
1333}
1334
1335private auto extremum(alias selector = "a < b", Range)(Range r)
1336 if (isInputRange!Range && !isInfinite!Range &&
1337 !is(typeof(unaryFun!selector(ElementType!(Range).init))))
1338{
1339 alias Element = ElementType!Range;
1340 Unqual!Element seed = r.front;
1341 r.popFront();
1342 return extremum!selector(r, seed);
1343}
1344
1345// if we only have one statement in the loop it can be optimized a lot better
1346private auto extremum(alias selector = "a < b", Range,
1347 RangeElementType = ElementType!Range)
1348 (Range r, RangeElementType seedElement)
1349 if (isInputRange!Range && !isInfinite!Range &&
1350 !is(CommonType!(ElementType!Range, RangeElementType) == void) &&
1351 !is(typeof(unaryFun!selector(ElementType!(Range).init))))
1352{
1353 alias Element = ElementType!Range;
1354 alias CommonElement = CommonType!(Element, RangeElementType);
1355 Unqual!CommonElement extremeElement = seedElement;
1356 alias selectorFun = binaryFun!selector;
1357
1358 // direct access via a random access range is faster
1359 static if (isRandomAccessRange!Range)
1360 {
1361 foreach (const i; 0 .. r.length)
1362 {
1363 if (selectorFun(r[i], extremeElement))
1364 {
1365 extremeElement = r[i];
1366 }
1367 }
1368 }
1369 else
1370 {
1371 while (!r.empty)
1372 {
1373 if (selectorFun(r.front, extremeElement))
1374 {
1375 extremeElement = r.front;
1376 }
1377 r.popFront();
1378 }
1379 }
1380 return extremeElement;
1381}
1382
1383@safe pure unittest
1384{
1385 // allows a custom map to select the extremum
1386 assert([[0, 4], [1, 2]].extremum!"a[0]" == [0, 4]);
1387 assert([[0, 4], [1, 2]].extremum!"a[1]" == [1, 2]);
1388
1389 // allows a custom selector for comparison
1390 assert([[0, 4], [1, 2]].extremum!("a[0]", "a > b") == [1, 2]);
1391 assert([[0, 4], [1, 2]].extremum!("a[1]", "a > b") == [0, 4]);
1392
1393 // use a custom comparator
1394 import std.math : cmp;
1395 assert([-2., 0, 5].extremum!cmp == 5.0);
1396 assert([-2., 0, 2].extremum!`cmp(a, b) < 0` == -2.0);
1397
1398 // combine with map
1399 import std.range : enumerate;
1400 assert([-3., 0, 5].enumerate.extremum!(`a.value`, cmp) == tuple(2, 5.0));
1401 assert([-2., 0, 2].enumerate.extremum!(`a.value`, `cmp(a, b) < 0`) == tuple(0, -2.0));
1402
1403 // seed with a custom value
1404 int[] arr;
1405 assert(arr.extremum(1) == 1);
1406}
1407
1408@safe pure nothrow unittest
1409{
1410 // 2d seeds
1411 int[][] arr2d;
1412 assert(arr2d.extremum([1]) == [1]);
1413
1414 // allow seeds of different types (implicit casting)
1415 assert(extremum([2, 3, 4], 1.5) == 1.5);
1416}
1417
1418@safe pure unittest
1419{
1420 import std.range : enumerate, iota;
1421
1422 // forward ranges
1423 assert(iota(1, 5).extremum() == 1);
1424 assert(iota(2, 5).enumerate.extremum!"a.value" == tuple(0, 2));
1425
1426 // should work with const
1427 const(int)[] immArr = [2, 1, 3];
1428 assert(immArr.extremum == 1);
1429
1430 // should work with immutable
1431 immutable(int)[] immArr2 = [2, 1, 3];
1432 assert(immArr2.extremum == 1);
1433
1434 // with strings
1435 assert(["b", "a", "c"].extremum == "a");
1436
1437 // with all dummy ranges
1438 import std.internal.test.dummyrange;
1439 foreach (DummyType; AllDummyRanges)
1440 {
1441 DummyType d;
1442 assert(d.extremum == 1);
1443 assert(d.extremum!(a => a) == 1);
1444 assert(d.extremum!`a > b` == 10);
1445 assert(d.extremum!(a => a, `a > b`) == 10);
1446 }
1447}
1448
1449@nogc @safe nothrow pure unittest
1450{
1451 static immutable arr = [7, 3, 4, 2, 1, 8];
1452 assert(arr.extremum == 1);
1453
1454 static immutable arr2d = [[1, 9], [3, 1], [4, 2]];
1455 assert(arr2d.extremum!"a[1]" == arr2d[1]);
1456}
1457
1458// find
1459/**
1460Finds an individual element in an input range. Elements of $(D
1461haystack) are compared with $(D needle) by using predicate $(D
1462pred). Performs $(BIGOH walkLength(haystack)) evaluations of $(D
1463pred).
1464
1465To _find the last occurrence of $(D needle) in $(D haystack), call $(D
1466find(retro(haystack), needle)). See $(REF retro, std,range).
1467
1468Params:
1469
1470pred = The predicate for comparing each element with the needle, defaulting to
1471$(D "a == b").
1472The negated predicate $(D "a != b") can be used to search instead for the first
1473element $(I not) matching the needle.
1474
1475haystack = The $(REF_ALTTEXT input range, isInputRange, std,range,primitives)
1476searched in.
1477
1478needle = The element searched for.
1479
1480Constraints:
1481
1482$(D isInputRange!InputRange && is(typeof(binaryFun!pred(haystack.front, needle)
1483: bool)))
1484
1485Returns:
1486
1487$(D haystack) advanced such that the front element is the one searched for;
1488that is, until $(D binaryFun!pred(haystack.front, needle)) is $(D true). If no
1489such position exists, returns an empty $(D haystack).
1490
1491See_Also:
1492 $(HTTP sgi.com/tech/stl/_find.html, STL's _find)
1493 */
1494InputRange find(alias pred = "a == b", InputRange, Element)(InputRange haystack, scope Element needle)
1495if (isInputRange!InputRange &&
1496 is (typeof(binaryFun!pred(haystack.front, needle)) : bool))
1497{
1498 alias R = InputRange;
1499 alias E = Element;
1500 alias predFun = binaryFun!pred;
1501 static if (is(typeof(pred == "a == b")))
1502 enum isDefaultPred = pred == "a == b";
1503 else
1504 enum isDefaultPred = false;
1505 enum isIntegralNeedle = isSomeChar!E || isIntegral!E || isBoolean!E;
1506
1507 alias EType = ElementType!R;
1508
1509 // If the haystack is a SortedRange we can use binary search to find the needle.
1510 // Works only for the default find predicate and any SortedRange predicate.
1511 // 8829 enhancement
1512 import std.range : SortedRange;
1513 static if (is(InputRange : SortedRange!TT, TT) && isDefaultPred)
1514 {
1515 auto lb = haystack.lowerBound(needle);
1516 if (lb.length == haystack.length || haystack[lb.length] != needle)
1517 return haystack[$ .. $];
1518
1519 return haystack[lb.length .. $];
1520 }
1521 else static if (isNarrowString!R)
1522 {
1523 alias EEType = ElementEncodingType!R;
1524 alias UEEType = Unqual!EEType;
1525
1526 //These are two special cases which can search without decoding the UTF stream.
1527 static if (isDefaultPred && isIntegralNeedle)
1528 {
1529 import std.utf : canSearchInCodeUnits;
1530
1531 //This special case deals with UTF8 search, when the needle
1532 //is represented by a single code point.
1533 //Note: "needle <= 0x7F" properly handles sign via unsigned promotion
1534 static if (is(UEEType == char))
1535 {
1536 if (!__ctfe && canSearchInCodeUnits!char(needle))
1537 {
1538 static R trustedMemchr(ref R haystack, ref E needle) @trusted nothrow pure
1539 {
1540 import core.stdc.string : memchr;
1541 auto ptr = memchr(haystack.ptr, needle, haystack.length);
1542 return ptr ?
1543 haystack[cast(char*) ptr - haystack.ptr .. $] :
1544 haystack[$ .. $];
1545 }
1546 return trustedMemchr(haystack, needle);
1547 }
1548 }
1549
1550 //Ditto, but for UTF16
1551 static if (is(UEEType == wchar))
1552 {
1553 if (canSearchInCodeUnits!wchar(needle))
1554 {
1555 foreach (i, ref EEType e; haystack)
1556 {
1557 if (e == needle)
1558 return haystack[i .. $];
1559 }
1560 return haystack[$ .. $];
1561 }
1562 }
1563 }
1564
1565 //Previous conditonal optimizations did not succeed. Fallback to
1566 //unconditional implementations
1567 static if (isDefaultPred)
1568 {
1569 import std.utf : encode;
1570
1571 //In case of default pred, it is faster to do string/string search.
1572 UEEType[is(UEEType == char) ? 4 : 2] buf;
1573
1574 size_t len = encode(buf, needle);
1575 return find(haystack, buf[0 .. len]);
1576 }
1577 else
1578 {
1579 import std.utf : decode;
1580
1581 //Explicit pred: we must test each character by the book.
1582 //We choose a manual decoding approach, because it is faster than
1583 //the built-in foreach, or doing a front/popFront for-loop.
1584 immutable len = haystack.length;
1585 size_t i = 0, next = 0;
1586 while (next < len)
1587 {
1588 if (predFun(decode(haystack, next), needle))
1589 return haystack[i .. $];
1590 i = next;
1591 }
1592 return haystack[$ .. $];
1593 }
1594 }
1595 else static if (isArray!R)
1596 {
1597 //10403 optimization
1598 static if (isDefaultPred && isIntegral!EType && EType.sizeof == 1 && isIntegralNeedle)
1599 {
1600 import std.algorithm.comparison : max, min;
1601
1602 R findHelper(ref R haystack, ref E needle) @trusted nothrow pure
1603 {
1604 import core.stdc.string : memchr;
1605
1606 EType* ptr = null;
1607 //Note: we use "min/max" to handle sign mismatch.
1608 if (min(EType.min, needle) == EType.min &&
1609 max(EType.max, needle) == EType.max)
1610 {
1611 ptr = cast(EType*) memchr(haystack.ptr, needle,
1612 haystack.length);
1613 }
1614
1615 return ptr ?
1616 haystack[ptr - haystack.ptr .. $] :
1617 haystack[$ .. $];
1618 }
1619
1620 if (!__ctfe)
1621 return findHelper(haystack, needle);
1622 }
1623
1624 //Default implementation.
1625 foreach (i, ref e; haystack)
1626 if (predFun(e, needle))
1627 return haystack[i .. $];
1628 return haystack[$ .. $];
1629 }
1630 else
1631 {
1632 //Everything else. Walk.
1633 for ( ; !haystack.empty; haystack.popFront() )
1634 {
1635 if (predFun(haystack.front, needle))
1636 break;
1637 }
1638 return haystack;
1639 }
1640}
1641
1642///
1643@safe unittest
1644{
1645 import std.algorithm.comparison : equal;
1646 import std.container : SList;
1647 import std.range;
1648 import std.range.primitives : empty;
1649
1650 auto arr = assumeSorted!"a < b"([1, 2, 4, 4, 4, 4, 5, 6, 9]);
1651 assert(find(arr, 4) == assumeSorted!"a < b"([4, 4, 4, 4, 5, 6, 9]));
1652 assert(find(arr, 1) == arr);
1653 assert(find(arr, 9) == assumeSorted!"a < b"([9]));
1654 assert(find!"a > b"(arr, 4) == assumeSorted!"a < b"([5, 6, 9]));
1655 assert(find!"a < b"(arr, 4) == arr);
1656 assert(find(arr, 0).empty());
1657 assert(find(arr, 10).empty());
1658 assert(find(arr, 8).empty());
1659
1660 auto r = assumeSorted!"a > b"([10, 7, 3, 1, 0, 0]);
1661 assert(find(r, 3) == assumeSorted!"a > b"([3, 1, 0, 0]));
1662 assert(find!"a > b"(r, 8) == r);
1663 assert(find!"a < b"(r, 5) == assumeSorted!"a > b"([3, 1, 0, 0]));
1664
1665 assert(find("hello, world", ',') == ", world");
1666 assert(find([1, 2, 3, 5], 4) == []);
1667 assert(equal(find(SList!int(1, 2, 3, 4, 5)[], 4), SList!int(4, 5)[]));
1668 assert(find!"a > b"([1, 2, 3, 5], 2) == [3, 5]);
1669
1670 auto a = [ 1, 2, 3 ];
1671 assert(find(a, 5).empty); // not found
1672 assert(!find(a, 2).empty); // found
1673
1674 // Case-insensitive find of a string
1675 string[] s = [ "Hello", "world", "!" ];
1676 assert(!find!("toLower(a) == b")(s, "hello").empty);
1677}
1678
1679@safe unittest
1680{
1681 import std.algorithm.comparison : equal;
1682 import std.container : SList;
1683
1684 auto lst = SList!int(1, 2, 5, 7, 3);
1685 assert(lst.front == 1);
1686 auto r = find(lst[], 5);
1687 assert(equal(r, SList!int(5, 7, 3)[]));
1688 assert(find([1, 2, 3, 5], 4).empty);
1689 assert(equal(find!"a > b"("hello", 'k'), "llo"));
1690}
1691
1692@safe pure nothrow unittest
1693{
1694 assert(!find ([1, 2, 3], 2).empty);
1695 assert(!find!((a,b)=>a == b)([1, 2, 3], 2).empty);
1696 assert(!find ([1, 2, 3], 2).empty);
1697 assert(!find!((a,b)=>a == b)([1, 2, 3], 2).empty);
1698}
1699
1700@safe pure unittest
1701{
1702 import std.meta : AliasSeq;
1703 foreach (R; AliasSeq!(string, wstring, dstring))
1704 {
1705 foreach (E; AliasSeq!(char, wchar, dchar))
1706 {
1707 assert(find ("hello world", 'w') == "world");
1708 assert(find!((a,b)=>a == b)("hello world", 'w') == "world");
1709 assert(find ("日c語", 'c') == "c語");
1710 assert(find!((a,b)=>a == b)("日c語", 'c') == "c語");
1711 assert(find ("0123456789", 'A').empty);
1712 static if (E.sizeof >= 2)
1713 {
1714 assert(find ("日本語", '本') == "本語");
1715 assert(find!((a,b)=>a == b)("日本語", '本') == "本語");
1716 }
1717 }
1718 }
1719}
1720
1721@safe unittest
1722{
1723 //CTFE
1724 static assert(find("abc", 'b') == "bc");
1725 static assert(find("日b語", 'b') == "b語");
1726 static assert(find("日本語", '本') == "本語");
1727 static assert(find([1, 2, 3], 2) == [2, 3]);
1728
1729 static assert(find ([1, 2, 3], 2));
1730 static assert(find!((a,b)=>a == b)([1, 2, 3], 2));
1731 static assert(find ([1, 2, 3], 2));
1732 static assert(find!((a,b)=>a == b)([1, 2, 3], 2));
1733}
1734
1735@safe unittest
1736{
1737 import std.exception : assertCTFEable;
1738 import std.meta : AliasSeq;
1739
1740 void dg() @safe pure nothrow
1741 {
1742 byte[] sarr = [1, 2, 3, 4];
1743 ubyte[] uarr = [1, 2, 3, 4];
1744 foreach (arr; AliasSeq!(sarr, uarr))
1745 {
1746 foreach (T; AliasSeq!(byte, ubyte, int, uint))
1747 {
1748 assert(find(arr, cast(T) 3) == arr[2 .. $]);
1749 assert(find(arr, cast(T) 9) == arr[$ .. $]);
1750 }
1751 assert(find(arr, 256) == arr[$ .. $]);
1752 }
1753 }
1754 dg();
1755 assertCTFEable!dg;
1756}
1757
1758@safe unittest
1759{
1760 // Bugzilla 11603
1761 enum Foo : ubyte { A }
1762 assert([Foo.A].find(Foo.A).empty == false);
1763
1764 ubyte x = 0;
1765 assert([x].find(x).empty == false);
1766}
1767
1768/**
1769Advances the input range $(D haystack) by calling $(D haystack.popFront)
1770until either $(D pred(haystack.front)), or $(D
1771haystack.empty). Performs $(BIGOH haystack.length) evaluations of $(D
1772pred).
1773
1774To _find the last element of a
1775$(REF_ALTTEXT bidirectional, isBidirectionalRange, std,range,primitives) $(D haystack) satisfying
1776$(D pred), call $(D find!(pred)(retro(haystack))). See $(REF retro, std,range).
1777
1778`find` behaves similar to `dropWhile` in other languages.
1779
1780Params:
1781
1782pred = The predicate for determining if a given element is the one being
1783searched for.
1784
1785haystack = The $(REF_ALTTEXT input range, isInputRange, std,range,primitives) to
1786search in.
1787
1788Returns:
1789
1790$(D haystack) advanced such that the front element is the one searched for;
1791that is, until $(D binaryFun!pred(haystack.front, needle)) is $(D true). If no
1792such position exists, returns an empty $(D haystack).
1793
1794See_Also:
1795 $(HTTP sgi.com/tech/stl/find_if.html, STL's find_if)
1796*/
1797InputRange find(alias pred, InputRange)(InputRange haystack)
1798if (isInputRange!InputRange)
1799{
1800 alias R = InputRange;
1801 alias predFun = unaryFun!pred;
1802 static if (isNarrowString!R)
1803 {
1804 import std.utf : decode;
1805
1806 immutable len = haystack.length;
1807 size_t i = 0, next = 0;
1808 while (next < len)
1809 {
1810 if (predFun(decode(haystack, next)))
1811 return haystack[i .. $];
1812 i = next;
1813 }
1814 return haystack[$ .. $];
1815 }
1816 else
1817 {
1818 //standard range
1819 for ( ; !haystack.empty; haystack.popFront() )
1820 {
1821 if (predFun(haystack.front))
1822 break;
1823 }
1824 return haystack;
1825 }
1826}
1827
1828///
1829@safe unittest
1830{
1831 auto arr = [ 1, 2, 3, 4, 1 ];
1832 assert(find!("a > 2")(arr) == [ 3, 4, 1 ]);
1833
1834 // with predicate alias
1835 bool pred(int x) { return x + 1 > 1.5; }
1836 assert(find!(pred)(arr) == arr);
1837}
1838
1839@safe pure unittest
1840{
1841 int[] r = [ 1, 2, 3 ];
1842 assert(find!(a=>a > 2)(r) == [3]);
1843 bool pred(int x) { return x + 1 > 1.5; }
1844 assert(find!(pred)(r) == r);
1845
1846 assert(find!(a=>a > 'v')("hello world") == "world");
1847 assert(find!(a=>a%4 == 0)("日本語") == "本語");
1848}
1849
1850/**
1851Finds the first occurrence of a forward range in another forward range.
1852
1853Performs $(BIGOH walkLength(haystack) * walkLength(needle)) comparisons in the
1854worst case. There are specializations that improve performance by taking
1855advantage of $(REF_ALTTEXT bidirectional range, isBidirectionalRange, std,range,primitives)
1856or random access in the given ranges (where possible), depending on the statistics
1857of the two ranges' content.
1858
1859Params:
1860
1861pred = The predicate to use for comparing respective elements from the haystack
1862and the needle. Defaults to simple equality $(D "a == b").
1863
1864haystack = The $(REF_ALTTEXT forward range, isForwardRange, std,range,primitives)
1865searched in.
1866
1867needle = The $(REF_ALTTEXT forward range, isForwardRange, std,range,primitives)
1868searched for.
1869
1870Returns:
1871
1872$(D haystack) advanced such that $(D needle) is a prefix of it (if no
1873such position exists, returns $(D haystack) advanced to termination).
1874 */
1875R1 find(alias pred = "a == b", R1, R2)(R1 haystack, scope R2 needle)
1876if (isForwardRange!R1 && isForwardRange!R2
1877 && is(typeof(binaryFun!pred(haystack.front, needle.front)) : bool))
1878{
1879 static if (!isRandomAccessRange!R1)
1880 {
1881 static if (is(typeof(pred == "a == b")) && pred == "a == b" && isSomeString!R1 && isSomeString!R2
1882 && haystack[0].sizeof == needle[0].sizeof)
1883 {
1884 // return cast(R1) find(representation(haystack), representation(needle));
1885 // Specialization for simple string search
1886 alias Representation =
1887 Select!(haystack[0].sizeof == 1, ubyte[],
1888 Select!(haystack[0].sizeof == 2, ushort[], uint[]));
1889 // Will use the array specialization
1890 static TO force(TO, T)(T r) @trusted { return cast(TO) r; }
1891 return force!R1(.find!(pred, Representation, Representation)
1892 (force!Representation(haystack), force!Representation(needle)));
1893 }
1894 else
1895 {
1896 return simpleMindedFind!pred(haystack, needle);
1897 }
1898 }
1899 else static if (!isBidirectionalRange!R2 || !hasSlicing!R1)
1900 {
1901 static if (!is(ElementType!R1 == ElementType!R2))
1902 {
1903 return simpleMindedFind!pred(haystack, needle);
1904 }
1905 else
1906 {
1907 // Prepare the search with needle's first element
1908 if (needle.empty)
1909 return haystack;
1910
1911 haystack = .find!pred(haystack, needle.front);
1912
1913 static if (hasLength!R1 && hasLength!R2 && is(typeof(takeNone(haystack)) == R1))
1914 {
1915 if (needle.length > haystack.length)
1916 return takeNone(haystack);
1917 }
1918 else
1919 {
1920 if (haystack.empty)
1921 return haystack;
1922 }
1923
1924 needle.popFront();
1925 size_t matchLen = 1;
1926
1927 // Loop invariant: haystack[0 .. matchLen] matches everything in
1928 // the initial needle that was popped out of needle.
1929 for (;;)
1930 {
1931 // Extend matchLength as much as possible
1932 for (;;)
1933 {
1934 import std.range : takeNone;
1935
1936 if (needle.empty || haystack.empty)
1937 return haystack;
1938
1939 static if (hasLength!R1 && is(typeof(takeNone(haystack)) == R1))
1940 {
1941 if (matchLen == haystack.length)
1942 return takeNone(haystack);
1943 }
1944
1945 if (!binaryFun!pred(haystack[matchLen], needle.front))
1946 break;
1947
1948 ++matchLen;
1949 needle.popFront();
1950 }
1951
1952 auto bestMatch = haystack[0 .. matchLen];
1953 haystack.popFront();
1954 haystack = .find!pred(haystack, bestMatch);
1955 }
1956 }
1957 }
1958 else // static if (hasSlicing!R1 && isBidirectionalRange!R2)
1959 {
1960 if (needle.empty) return haystack;
1961
1962 static if (hasLength!R2)
1963 {
1964 immutable needleLength = needle.length;
1965 }
1966 else
1967 {
1968 immutable needleLength = walkLength(needle.save);
1969 }
1970 if (needleLength > haystack.length)
1971 {
1972 return haystack[haystack.length .. haystack.length];
1973 }
1974 // Optimization in case the ranges are both SortedRanges.
1975 // Binary search can be used to find the first occurence
1976 // of the first element of the needle in haystack.
1977 // When it is found O(walklength(needle)) steps are performed.
1978 // 8829 enhancement
1979 import std.algorithm.comparison : mismatch;
1980 import std.range : SortedRange;
1981 static if (is(R1 == R2)
1982 && is(R1 : SortedRange!TT, TT)
1983 && pred == "a == b")
1984 {
1985 auto needleFirstElem = needle[0];
1986 auto partitions = haystack.trisect(needleFirstElem);
1987 auto firstElemLen = partitions[1].length;
1988 size_t count = 0;
1989
1990 if (firstElemLen == 0)
1991 return haystack[$ .. $];
1992
1993 while (needle.front() == needleFirstElem)
1994 {
1995 needle.popFront();
1996 ++count;
1997
1998 if (count > firstElemLen)
1999 return haystack[$ .. $];
2000 }
2001
2002 auto m = mismatch(partitions[2], needle);
2003
2004 if (m[1].empty)
2005 return haystack[partitions[0].length + partitions[1].length - count .. $];
2006 }
2007 else static if (isRandomAccessRange!R2)
2008 {
2009 immutable lastIndex = needleLength - 1;
2010 auto last = needle[lastIndex];
2011 size_t j = lastIndex, skip = 0;
2012 for (; j < haystack.length;)
2013 {
2014 if (!binaryFun!pred(haystack[j], last))
2015 {
2016 ++j;
2017 continue;
2018 }
2019 immutable k = j - lastIndex;
2020 // last elements match
2021 for (size_t i = 0;; ++i)
2022 {
2023 if (i == lastIndex)
2024 return haystack[k .. haystack.length];
2025 if (!binaryFun!pred(haystack[k + i], needle[i]))
2026 break;
2027 }
2028 if (skip == 0)
2029 {
2030 skip = 1;
2031 while (skip < needleLength && needle[needleLength - 1 - skip] != needle[needleLength - 1])
2032 {
2033 ++skip;
2034 }
2035 }
2036 j += skip;
2037 }
2038 }
2039 else
2040 {
2041 // @@@BUG@@@
2042 // auto needleBack = moveBack(needle);
2043 // Stage 1: find the step
2044 size_t step = 1;
2045 auto needleBack = needle.back;
2046 needle.popBack();
2047 for (auto i = needle.save; !i.empty && i.back != needleBack;
2048 i.popBack(), ++step)
2049 {
2050 }
2051 // Stage 2: linear find
2052 size_t scout = needleLength - 1;
2053 for (;;)
2054 {
2055 if (scout >= haystack.length)
2056 break;
2057 if (!binaryFun!pred(haystack[scout], needleBack))
2058 {
2059 ++scout;
2060 continue;
2061 }
2062 // Found a match with the last element in the needle
2063 auto cand = haystack[scout + 1 - needleLength .. haystack.length];
2064 if (startsWith!pred(cand, needle))
2065 {
2066 // found
2067 return cand;
2068 }
2069 scout += step;
2070 }
2071 }
2072 return haystack[haystack.length .. haystack.length];
2073 }
2074}
2075
2076///
2077@safe unittest
2078{
2079 import std.container : SList;
2080 import std.range.primitives : empty;
2081 import std.typecons : Tuple;
2082
2083 assert(find("hello, world", "World").empty);
2084 assert(find("hello, world", "wo") == "world");
2085 assert([1, 2, 3, 4].find(SList!int(2, 3)[]) == [2, 3, 4]);
2086 alias C = Tuple!(int, "x", int, "y");
2087 auto a = [C(1,0), C(2,0), C(3,1), C(4,0)];
2088 assert(a.find!"a.x == b"([2, 3]) == [C(2,0), C(3,1), C(4,0)]);
2089 assert(a[1 .. $].find!"a.x == b"([2, 3]) == [C(2,0), C(3,1), C(4,0)]);
2090}
2091
2092@safe unittest
2093{
2094 import std.container : SList;
2095 alias C = Tuple!(int, "x", int, "y");
2096 assert([C(1,0), C(2,0), C(3,1), C(4,0)].find!"a.x == b"(SList!int(2, 3)[]) == [C(2,0), C(3,1), C(4,0)]);
2097}
2098
2099@safe unittest
2100{
2101 import std.algorithm.comparison : equal;
2102 import std.container : SList;
2103
2104 auto lst = SList!int(1, 2, 5, 7, 3);
2105 static assert(isForwardRange!(int[]));
2106 static assert(isForwardRange!(typeof(lst[])));
2107 auto r = find(lst[], [2, 5]);
2108 assert(equal(r, SList!int(2, 5, 7, 3)[]));
2109}
2110
2111@safe unittest
2112{
2113 import std.range;
2114 import std.stdio;
2115
2116 auto r1 = assumeSorted([1, 2, 3, 3, 3, 4, 5, 6, 7, 8, 8, 8, 10]);
2117 auto r2 = assumeSorted([3, 3, 4, 5, 6, 7, 8, 8]);
2118 auto r3 = assumeSorted([3, 4, 5, 6, 7, 8]);
2119 auto r4 = assumeSorted([4, 5, 6]);
2120 auto r5 = assumeSorted([12, 13]);
2121 auto r6 = assumeSorted([8, 8, 10, 11]);
2122 auto r7 = assumeSorted([3, 3, 3, 3, 3, 3, 3]);
2123
2124 assert(find(r1, r2) == assumeSorted([3, 3, 4, 5, 6, 7, 8, 8, 8, 10]));
2125 assert(find(r1, r3) == assumeSorted([3, 4, 5, 6, 7, 8, 8, 8, 10]));
2126 assert(find(r1, r4) == assumeSorted([4, 5, 6, 7, 8, 8, 8, 10]));
2127 assert(find(r1, r5).empty());
2128 assert(find(r1, r6).empty());
2129 assert(find(r1, r7).empty());
2130}
2131
2132@safe unittest
2133{
2134 import std.algorithm.comparison : equal;
2135 // @@@BUG@@@ removing static below makes unittest fail
2136 static struct BiRange
2137 {
2138 int[] payload;
2139 @property bool empty() { return payload.empty; }
2140 @property BiRange save() { return this; }
2141 @property ref int front() { return payload[0]; }
2142 @property ref int back() { return payload[$ - 1]; }
2143 void popFront() { return payload.popFront(); }
2144 void popBack() { return payload.popBack(); }
2145 }
2146 auto r = BiRange([1, 2, 3, 10, 11, 4]);
2147 assert(equal(find(r, [10, 11]), [10, 11, 4]));
2148}
2149
2150@safe unittest
2151{
2152 import std.container : SList;
2153
2154 assert(find([ 1, 2, 3 ], SList!int(2, 3)[]) == [ 2, 3 ]);
2155 assert(find([ 1, 2, 1, 2, 3, 3 ], SList!int(2, 3)[]) == [ 2, 3, 3 ]);
2156}
2157
2158//Bug# 8334
2159@safe unittest
2160{
2161 import std.algorithm.iteration : filter;
2162 import std.range;
2163
2164 auto haystack = [1, 2, 3, 4, 1, 9, 12, 42];
2165 auto needle = [12, 42, 27];
2166
2167 //different overload of find, but it's the base case.
2168 assert(find(haystack, needle).empty);
2169
2170 assert(find(haystack, takeExactly(filter!"true"(needle), 3)).empty);
2171 assert(find(haystack, filter!"true"(needle)).empty);
2172}
2173
2174// Internally used by some find() overloads above
2175private R1 simpleMindedFind(alias pred, R1, R2)(R1 haystack, scope R2 needle)
2176{
2177 enum estimateNeedleLength = hasLength!R1 && !hasLength!R2;
2178
2179 static if (hasLength!R1)
2180 {
2181 static if (!hasLength!R2)
2182 size_t estimatedNeedleLength = 0;
2183 else
2184 immutable size_t estimatedNeedleLength = needle.length;
2185 }
2186
2187 bool haystackTooShort()
2188 {
2189 static if (estimateNeedleLength)
2190 {
2191 return haystack.length < estimatedNeedleLength;
2192 }
2193 else
2194 {
2195 return haystack.empty;
2196 }
2197 }
2198
2199 searching:
2200 for (;; haystack.popFront())
2201 {
2202 if (haystackTooShort())
2203 {
2204 // Failed search
2205 static if (hasLength!R1)
2206 {
2207 static if (is(typeof(haystack[haystack.length ..
2208 haystack.length]) : R1))
2209 return haystack[haystack.length .. haystack.length];
2210 else
2211 return R1.init;
2212 }
2213 else
2214 {
2215 assert(haystack.empty);
2216 return haystack;
2217 }
2218 }
2219 static if (estimateNeedleLength)
2220 size_t matchLength = 0;
2221 for (auto h = haystack.save, n = needle.save;
2222 !n.empty;
2223 h.popFront(), n.popFront())
2224 {
2225 if (h.empty || !binaryFun!pred(h.front, n.front))
2226 {
2227 // Failed searching n in h
2228 static if (estimateNeedleLength)
2229 {
2230 if (estimatedNeedleLength < matchLength)
2231 estimatedNeedleLength = matchLength;
2232 }
2233 continue searching;
2234 }
2235 static if (estimateNeedleLength)
2236 ++matchLength;
2237 }
2238 break;
2239 }
2240 return haystack;
2241}
2242
2243@safe unittest
2244{
2245 // Test simpleMindedFind for the case where both haystack and needle have
2246 // length.
2247 struct CustomString
2248 {
2249 @safe:
2250 string _impl;
2251
2252 // This is what triggers issue 7992.
2253 @property size_t length() const { return _impl.length; }
2254 @property void length(size_t len) { _impl.length = len; }
2255
2256 // This is for conformance to the forward range API (we deliberately
2257 // make it non-random access so that we will end up in
2258 // simpleMindedFind).
2259 @property bool empty() const { return _impl.empty; }
2260 @property dchar front() const { return _impl.front; }
2261 void popFront() { _impl.popFront(); }
2262 @property CustomString save() { return this; }
2263 }
2264
2265 // If issue 7992 occurs, this will throw an exception from calling
2266 // popFront() on an empty range.
2267 auto r = find(CustomString("a"), CustomString("b"));
2268 assert(r.empty);
2269}
2270
2271/**
2272Finds two or more $(D needles) into a $(D haystack). The predicate $(D
2273pred) is used throughout to compare elements. By default, elements are
2274compared for equality.
2275
2276Params:
2277
2278pred = The predicate to use for comparing elements.
2279
2280haystack = The target of the search. Must be an input range.
2281If any of $(D needles) is a range with elements comparable to
2282elements in $(D haystack), then $(D haystack) must be a
2283$(REF_ALTTEXT forward range, isForwardRange, std,range,primitives)
2284such that the search can backtrack.
2285
2286needles = One or more items to search for. Each of $(D needles) must
2287be either comparable to one element in $(D haystack), or be itself a
2288forward range with elements comparable with elements in
2289$(D haystack).
2290
2291Returns:
2292
2293A tuple containing $(D haystack) positioned to match one of the
2294needles and also the 1-based index of the matching element in $(D
2295needles) (0 if none of $(D needles) matched, 1 if $(D needles[0])
2296matched, 2 if $(D needles[1]) matched...). The first needle to be found
2297will be the one that matches. If multiple needles are found at the
2298same spot in the range, then the shortest one is the one which matches
2299(if multiple needles of the same length are found at the same spot (e.g
2300$(D "a") and $(D 'a')), then the left-most of them in the argument list
2301matches).
2302
2303The relationship between $(D haystack) and $(D needles) simply means
2304that one can e.g. search for individual $(D int)s or arrays of $(D
2305int)s in an array of $(D int)s. In addition, if elements are
2306individually comparable, searches of heterogeneous types are allowed
2307as well: a $(D double[]) can be searched for an $(D int) or a $(D
2308short[]), and conversely a $(D long) can be searched for a $(D float)
2309or a $(D double[]). This makes for efficient searches without the need
2310to coerce one side of the comparison into the other's side type.
2311
2312The complexity of the search is $(BIGOH haystack.length *
2313max(needles.length)). (For needles that are individual items, length
2314is considered to be 1.) The strategy used in searching several
2315subranges at once maximizes cache usage by moving in $(D haystack) as
2316few times as possible.
2317 */
2318Tuple!(Range, size_t) find(alias pred = "a == b", Range, Ranges...)
2319(Range haystack, Ranges needles)
2320if (Ranges.length > 1 && is(typeof(startsWith!pred(haystack, needles))))
2321{
2322 for (;; haystack.popFront())
2323 {
2324 size_t r = startsWith!pred(haystack, needles);
2325 if (r || haystack.empty)
2326 {
2327 return tuple(haystack, r);
2328 }
2329 }
2330}
2331
2332///
2333@safe unittest
2334{
2335 import std.typecons : tuple;
2336 int[] a = [ 1, 4, 2, 3 ];
2337 assert(find(a, 4) == [ 4, 2, 3 ]);
2338 assert(find(a, [ 1, 4 ]) == [ 1, 4, 2, 3 ]);
2339 assert(find(a, [ 1, 3 ], 4) == tuple([ 4, 2, 3 ], 2));
2340 // Mixed types allowed if comparable
2341 assert(find(a, 5, [ 1.2, 3.5 ], 2.0) == tuple([ 2, 3 ], 3));
2342}
2343
2344@safe unittest
2345{
2346 auto s1 = "Mary has a little lamb";
2347 assert(find(s1, "has a", "has an") == tuple("has a little lamb", 1));
2348 assert(find(s1, 't', "has a", "has an") == tuple("has a little lamb", 2));
2349 assert(find(s1, 't', "has a", 'y', "has an") == tuple("y has a little lamb", 3));
2350 assert(find("abc", "bc").length == 2);
2351}
2352
2353@safe unittest
2354{
2355 import std.algorithm.internal : rndstuff;
2356 import std.meta : AliasSeq;
2357 import std.uni : toUpper;
2358
2359 int[] a = [ 1, 2, 3 ];
2360 assert(find(a, 5).empty);
2361 assert(find(a, 2) == [2, 3]);
2362
2363 foreach (T; AliasSeq!(int, double))
2364 {
2365 auto b = rndstuff!(T)();
2366 if (!b.length) continue;
2367 b[$ / 2] = 200;
2368 b[$ / 4] = 200;
2369 assert(find(b, 200).length == b.length - b.length / 4);
2370 }
2371
2372 // Case-insensitive find of a string
2373 string[] s = [ "Hello", "world", "!" ];
2374 assert(find!("toUpper(a) == toUpper(b)")(s, "hello").length == 3);
2375
2376 static bool f(string a, string b) { return toUpper(a) == toUpper(b); }
2377 assert(find!(f)(s, "hello").length == 3);
2378}
2379
2380@safe unittest
2381{
2382 import std.algorithm.comparison : equal;
2383 import std.algorithm.internal : rndstuff;
2384 import std.meta : AliasSeq;
2385 import std.range : retro;
2386
2387 int[] a = [ 1, 2, 3, 2, 6 ];
2388 assert(find(retro(a), 5).empty);
2389 assert(equal(find(retro(a), 2), [ 2, 3, 2, 1 ][]));
2390
2391 foreach (T; AliasSeq!(int, double))
2392 {
2393 auto b = rndstuff!(T)();
2394 if (!b.length) continue;
2395 b[$ / 2] = 200;
2396 b[$ / 4] = 200;
2397 assert(find(retro(b), 200).length ==
2398 b.length - (b.length - 1) / 2);
2399 }
2400}
2401
2402@safe unittest
2403{
2404 import std.algorithm.comparison : equal;
2405 import std.internal.test.dummyrange;
2406
2407 int[] a = [ -1, 0, 1, 2, 3, 4, 5 ];
2408 int[] b = [ 1, 2, 3 ];
2409 assert(find(a, b) == [ 1, 2, 3, 4, 5 ]);
2410 assert(find(b, a).empty);
2411
2412 foreach (DummyType; AllDummyRanges)
2413 {
2414 DummyType d;
2415 auto findRes = find(d, 5);
2416 assert(equal(findRes, [5,6,7,8,9,10]));
2417 }
2418}
2419
2420/**
2421 * Finds $(D needle) in $(D haystack) efficiently using the
2422 * $(LINK2 https://en.wikipedia.org/wiki/Boyer%E2%80%93Moore_string_search_algorithm,
2423 * Boyer-Moore) method.
2424 *
2425 * Params:
2426 * haystack = A random-access range with length and slicing.
2427 * needle = A $(LREF BoyerMooreFinder).
2428 *
2429 * Returns:
2430 * $(D haystack) advanced such that $(D needle) is a prefix of it (if no
2431 * such position exists, returns $(D haystack) advanced to termination).
2432 */
2433RandomAccessRange find(RandomAccessRange, alias pred, InputRange)(
2434 RandomAccessRange haystack, scope BoyerMooreFinder!(pred, InputRange) needle)
2435{
2436 return needle.beFound(haystack);
2437}
2438
2439@safe unittest
2440{
2441 string h = "/homes/aalexand/d/dmd/bin/../lib/libphobos.a(dmain2.o)"~
2442 "(.gnu.linkonce.tmain+0x74): In function `main' undefined reference"~
2443 " to `_Dmain':";
2444 string[] ns = ["libphobos", "function", " undefined", "`", ":"];
2445 foreach (n ; ns)
2446 {
2447 auto p = find(h, boyerMooreFinder(n));
2448 assert(!p.empty);
2449 }
2450}
2451
2452///
2453@safe unittest
2454{
2455 import std.range.primitives : empty;
2456 int[] a = [ -1, 0, 1, 2, 3, 4, 5 ];
2457 int[] b = [ 1, 2, 3 ];
2458
2459 assert(find(a, boyerMooreFinder(b)) == [ 1, 2, 3, 4, 5 ]);
2460 assert(find(b, boyerMooreFinder(a)).empty);
2461}
2462
2463@safe unittest
2464{
2465 auto bm = boyerMooreFinder("for");
2466 auto match = find("Moor", bm);
2467 assert(match.empty);
2468}
2469
2470// canFind
2471/++
2472Convenience function. Like find, but only returns whether or not the search
2473was successful.
2474
2475See_Also:
2476$(LREF among) for checking a value against multiple possibilities.
2477 +/
2478template canFind(alias pred="a == b")
2479{
2480 import std.meta : allSatisfy;
2481
2482 /++
2483 Returns $(D true) if and only if any value $(D v) found in the
2484 input range $(D range) satisfies the predicate $(D pred).
2485 Performs (at most) $(BIGOH haystack.length) evaluations of $(D pred).
2486 +/
2487 bool canFind(Range)(Range haystack)
2488 if (is(typeof(find!pred(haystack))))
2489 {
2490 return any!pred(haystack);
2491 }
2492
2493 /++
2494 Returns $(D true) if and only if $(D needle) can be found in $(D
2495 range). Performs $(BIGOH haystack.length) evaluations of $(D pred).
2496 +/
2497 bool canFind(Range, Element)(Range haystack, scope Element needle)
2498 if (is(typeof(find!pred(haystack, needle))))
2499 {
2500 return !find!pred(haystack, needle).empty;
2501 }
2502
2503 /++
2504 Returns the 1-based index of the first needle found in $(D haystack). If no
2505 needle is found, then $(D 0) is returned.
2506
2507 So, if used directly in the condition of an if statement or loop, the result
2508 will be $(D true) if one of the needles is found and $(D false) if none are
2509 found, whereas if the result is used elsewhere, it can either be cast to
2510 $(D bool) for the same effect or used to get which needle was found first
2511 without having to deal with the tuple that $(D LREF find) returns for the
2512 same operation.
2513 +/
2514 size_t canFind(Range, Ranges...)(Range haystack, scope Ranges needles)
2515 if (Ranges.length > 1 &&
2516 allSatisfy!(isForwardRange, Ranges) &&
2517 is(typeof(find!pred(haystack, needles))))
2518 {
2519 return find!pred(haystack, needles)[1];
2520 }
2521}
2522
2523///
2524@safe unittest
2525{
2526 assert(canFind([0, 1, 2, 3], 2) == true);
2527 assert(canFind([0, 1, 2, 3], [1, 2], [2, 3]));
2528 assert(canFind([0, 1, 2, 3], [1, 2], [2, 3]) == 1);
2529 assert(canFind([0, 1, 2, 3], [1, 7], [2, 3]));
2530 assert(canFind([0, 1, 2, 3], [1, 7], [2, 3]) == 2);
2531
2532 assert(canFind([0, 1, 2, 3], 4) == false);
2533 assert(!canFind([0, 1, 2, 3], [1, 3], [2, 4]));
2534 assert(canFind([0, 1, 2, 3], [1, 3], [2, 4]) == 0);
2535}
2536
2537/**
2538 * Example using a custom predicate.
2539 * Note that the needle appears as the second argument of the predicate.
2540 */
2541@safe unittest
2542{
2543 auto words = [
2544 "apple",
2545 "beeswax",
2546 "cardboard"
2547 ];
2548 assert(!canFind(words, "bees"));
2549 assert( canFind!((string a, string b) => a.startsWith(b))(words, "bees"));
2550}
2551
2552@safe unittest
2553{
2554 import std.algorithm.internal : rndstuff;
2555
2556 auto a = rndstuff!(int)();
2557 if (a.length)
2558 {
2559 auto b = a[a.length / 2];
2560 assert(canFind(a, b));
2561 }
2562}
2563
2564@safe unittest
2565{
2566 import std.algorithm.comparison : equal;
2567 assert(equal!(canFind!"a < b")([[1, 2, 3], [7, 8, 9]], [2, 8]));
2568}
2569
2570// findAdjacent
2571/**
2572Advances $(D r) until it finds the first two adjacent elements $(D a),
2573$(D b) that satisfy $(D pred(a, b)). Performs $(BIGOH r.length)
2574evaluations of $(D pred).
2575
2576Params:
2577 pred = The predicate to satisfy.
2578 r = A $(REF_ALTTEXT forward range, isForwardRange, std,range,primitives) to
2579 search in.
2580
2581Returns:
2582$(D r) advanced to the first occurrence of two adjacent elements that satisfy
2583the given predicate. If there are no such two elements, returns $(D r) advanced
2584until empty.
2585
2586See_Also:
2587 $(HTTP sgi.com/tech/stl/adjacent_find.html, STL's adjacent_find)
2588*/
2589Range findAdjacent(alias pred = "a == b", Range)(Range r)
2590if (isForwardRange!(Range))
2591{
2592 auto ahead = r.save;
2593 if (!ahead.empty)
2594 {
2595 for (ahead.popFront(); !ahead.empty; r.popFront(), ahead.popFront())
2596 {
2597 if (binaryFun!(pred)(r.front, ahead.front)) return r;
2598 }
2599 }
2600 static if (!isInfinite!Range)
2601 return ahead;
2602}
2603
2604///
2605@safe unittest
2606{
2607 int[] a = [ 11, 10, 10, 9, 8, 8, 7, 8, 9 ];
2608 auto r = findAdjacent(a);
2609 assert(r == [ 10, 10, 9, 8, 8, 7, 8, 9 ]);
2610 auto p = findAdjacent!("a < b")(a);
2611 assert(p == [ 7, 8, 9 ]);
2612
2613}
2614
2615@safe unittest
2616{
2617 import std.algorithm.comparison : equal;
2618 import std.internal.test.dummyrange;
2619 import std.range;
2620
2621 int[] a = [ 11, 10, 10, 9, 8, 8, 7, 8, 9 ];
2622 auto p = findAdjacent(a);
2623 assert(p == [10, 10, 9, 8, 8, 7, 8, 9 ]);
2624 p = findAdjacent!("a < b")(a);
2625 assert(p == [7, 8, 9]);
2626 // empty
2627 a = [];
2628 p = findAdjacent(a);
2629 assert(p.empty);
2630 // not found
2631 a = [ 1, 2, 3, 4, 5 ];
2632 p = findAdjacent(a);
2633 assert(p.empty);
2634 p = findAdjacent!"a > b"(a);
2635 assert(p.empty);
2636 ReferenceForwardRange!int rfr = new ReferenceForwardRange!int([1, 2, 3, 2, 2, 3]);
2637 assert(equal(findAdjacent(rfr), [2, 2, 3]));
2638
2639 // Issue 9350
2640 assert(!repeat(1).findAdjacent().empty);
2641}
2642
2643// findAmong
2644/**
2645Searches the given range for an element that matches one of the given choices.
2646
2647Advances $(D seq) by calling $(D seq.popFront) until either
2648$(D find!(pred)(choices, seq.front)) is $(D true), or $(D seq) becomes empty.
2649Performs $(BIGOH seq.length * choices.length) evaluations of $(D pred).
2650
2651Params:
2652 pred = The predicate to use for determining a match.
2653 seq = The $(REF_ALTTEXT input range, isInputRange, std,range,primitives) to
2654 search.
2655 choices = A $(REF_ALTTEXT forward range, isForwardRange, std,range,primitives)
2656 of possible choices.
2657
2658Returns:
2659$(D seq) advanced to the first matching element, or until empty if there are no
2660matching elements.
2661
2662See_Also:
2663 $(HTTP sgi.com/tech/stl/find_first_of.html, STL's find_first_of)
2664*/
2665InputRange findAmong(alias pred = "a == b", InputRange, ForwardRange)(
2666 InputRange seq, ForwardRange choices)
2667if (isInputRange!InputRange && isForwardRange!ForwardRange)
2668{
2669 for (; !seq.empty && find!pred(choices, seq.front).empty; seq.popFront())
2670 {
2671 }
2672 return seq;
2673}
2674
2675///
2676@safe unittest
2677{
2678 int[] a = [ -1, 0, 1, 2, 3, 4, 5 ];
2679 int[] b = [ 3, 1, 2 ];
2680 assert(findAmong(a, b) == a[2 .. $]);
2681}
2682
2683@safe unittest
2684{
2685 int[] a = [ -1, 0, 2, 1, 2, 3, 4, 5 ];
2686 int[] b = [ 1, 2, 3 ];
2687 assert(findAmong(a, b) == [2, 1, 2, 3, 4, 5 ]);
2688 assert(findAmong(b, [ 4, 6, 7 ][]).empty);
2689 assert(findAmong!("a == b")(a, b).length == a.length - 2);
2690 assert(findAmong!("a == b")(b, [ 4, 6, 7 ][]).empty);
2691}
2692
2693// findSkip
2694/**
2695 * Finds $(D needle) in $(D haystack) and positions $(D haystack)
2696 * right after the first occurrence of $(D needle).
2697 *
2698 * Params:
2699 * haystack = The
2700 * $(REF_ALTTEXT forward range, isForwardRange, std,range,primitives) to search
2701 * in.
2702 * needle = The
2703 * $(REF_ALTTEXT forward range, isForwardRange, std,range,primitives) to search
2704 * for.
2705 *
2706 * Returns: $(D true) if the needle was found, in which case $(D haystack) is
2707 * positioned after the end of the first occurrence of $(D needle); otherwise
2708 * $(D false), leaving $(D haystack) untouched.
2709 */
2710bool findSkip(alias pred = "a == b", R1, R2)(ref R1 haystack, R2 needle)
2711if (isForwardRange!R1 && isForwardRange!R2
2712 && is(typeof(binaryFun!pred(haystack.front, needle.front))))
2713{
2714 auto parts = findSplit!pred(haystack, needle);
2715 if (parts[1].empty) return false;
2716 // found
2717 haystack = parts[2];
2718 return true;
2719}
2720
2721///
2722@safe unittest
2723{
2724 import std.range.primitives : empty;
2725 // Needle is found; s is replaced by the substring following the first
2726 // occurrence of the needle.
2727 string s = "abcdef";
2728 assert(findSkip(s, "cd") && s == "ef");
2729
2730 // Needle is not found; s is left untouched.
2731 s = "abcdef";
2732 assert(!findSkip(s, "cxd") && s == "abcdef");
2733
2734 // If the needle occurs at the end of the range, the range is left empty.
2735 s = "abcdef";
2736 assert(findSkip(s, "def") && s.empty);
2737}
2738
2739/**
2740These functions find the first occurrence of `needle` in `haystack` and then
2741split `haystack` as follows.
2742
2743`findSplit` returns a tuple `result` containing $(I three) ranges. `result[0]`
2744is the portion of `haystack` before `needle`, `result[1]` is the portion of
2745`haystack` that matches `needle`, and `result[2]` is the portion of `haystack`
2746after the match. If `needle` was not found, `result[0]` comprehends `haystack`
2747entirely and `result[1]` and `result[2]` are empty.
2748
2749`findSplitBefore` returns a tuple `result` containing two ranges. `result[0]` is
2750the portion of `haystack` before `needle`, and `result[1]` is the balance of
2751`haystack` starting with the match. If `needle` was not found, `result[0]`
2752comprehends `haystack` entirely and `result[1]` is empty.
2753
2754`findSplitAfter` returns a tuple `result` containing two ranges.
2755`result[0]` is the portion of `haystack` up to and including the
2756match, and `result[1]` is the balance of `haystack` starting
2757after the match. If `needle` was not found, `result[0]` is empty
2758and `result[1]` is `haystack`.
2759
2760In all cases, the concatenation of the returned ranges spans the
2761entire `haystack`.
2762
2763If `haystack` is a random-access range, all three components of the tuple have
2764the same type as `haystack`. Otherwise, `haystack` must be a
2765$(REF_ALTTEXT forward range, isForwardRange, std,range,primitives) and
2766the type of `result[0]` and `result[1]` is the same as $(REF takeExactly,
2767std,range).
2768
2769Params:
2770 pred = Predicate to use for comparing needle against haystack.
2771 haystack = The range to search.
2772 needle = What to look for.
2773
2774Returns:
2775
2776A sub-type of `Tuple!()` of the split portions of `haystack` (see above for
2777details). This sub-type of `Tuple!()` has `opCast` defined for `bool`. This
2778`opCast` returns `true` when the separating `needle` was found
2779(`!result[1].empty`) and `false` otherwise. This enables the convenient idiom
2780shown in the following example.
2781
2782Example:
2783---
2784if (const split = haystack.findSplit(needle))
2785{
2786 doSomethingWithSplit(split);
2787}
2788---
2789 */
2790auto findSplit(alias pred = "a == b", R1, R2)(R1 haystack, R2 needle)
2791if (isForwardRange!R1 && isForwardRange!R2)
2792{
2793 static struct Result(S1, S2) if (isForwardRange!S1 &&
2794 isForwardRange!S2)
2795 {
2796 this(S1 pre, S1 separator, S2 post)
2797 {
2798 asTuple = typeof(asTuple)(pre, separator, post);
2799 }
2800 void opAssign(typeof(asTuple) rhs)
2801 {
2802 asTuple = rhs;
2803 }
2804 Tuple!(S1, S1, S2) asTuple;
2805 bool opCast(T : bool)()
2806 {
2807 return !asTuple[1].empty;
2808 }
2809 alias asTuple this;
2810 }
2811
2812 static if (isSomeString!R1 && isSomeString!R2
2813 || (isRandomAccessRange!R1 && hasSlicing!R1 && hasLength!R1 && hasLength!R2))
2814 {
2815 auto balance = find!pred(haystack, needle);
2816 immutable pos1 = haystack.length - balance.length;
2817 immutable pos2 = balance.empty ? pos1 : pos1 + needle.length;
2818 return Result!(typeof(haystack[0 .. pos1]),
2819 typeof(haystack[pos2 .. haystack.length]))(haystack[0 .. pos1],
2820 haystack[pos1 .. pos2],
2821 haystack[pos2 .. haystack.length]);
2822 }
2823 else
2824 {
2825 import std.range : takeExactly;
2826 auto original = haystack.save;
2827 auto h = haystack.save;
2828 auto n = needle.save;
2829 size_t pos1, pos2;
2830 while (!n.empty && !h.empty)
2831 {
2832 if (binaryFun!pred(h.front, n.front))
2833 {
2834 h.popFront();
2835 n.popFront();
2836 ++pos2;
2837 }
2838 else
2839 {
2840 haystack.popFront();
2841 n = needle.save;
2842 h = haystack.save;
2843 pos2 = ++pos1;
2844 }
2845 }
2846 return Result!(typeof(takeExactly(original, pos1)),
2847 typeof(h))(takeExactly(original, pos1),
2848 takeExactly(haystack, pos2 - pos1),
2849 h);
2850 }
2851}
2852
2853/// Ditto
2854auto findSplitBefore(alias pred = "a == b", R1, R2)(R1 haystack, R2 needle)
2855if (isForwardRange!R1 && isForwardRange!R2)
2856{
2857 static struct Result(S1, S2) if (isForwardRange!S1 &&
2858 isForwardRange!S2)
2859 {
2860 this(S1 pre, S2 post)
2861 {
2862 asTuple = typeof(asTuple)(pre, post);
2863 }
2864 void opAssign(typeof(asTuple) rhs)
2865 {
2866 asTuple = rhs;
2867 }
2868 Tuple!(S1, S2) asTuple;
2869 bool opCast(T : bool)()
2870 {
2871 return !asTuple[0].empty;
2872 }
2873 alias asTuple this;
2874 }
2875
2876 static if (isSomeString!R1 && isSomeString!R2
2877 || (isRandomAccessRange!R1 && hasLength!R1 && hasSlicing!R1 && hasLength!R2))
2878 {
2879 auto balance = find!pred(haystack, needle);
2880 immutable pos = haystack.length - balance.length;
2881 return Result!(typeof(haystack[0 .. pos]),
2882 typeof(haystack[pos .. haystack.length]))(haystack[0 .. pos],
2883 haystack[pos .. haystack.length]);
2884 }
2885 else
2886 {
2887 import std.range : takeExactly;
2888 auto original = haystack.save;
2889 auto h = haystack.save;
2890 auto n = needle.save;
2891 size_t pos;
2892 while (!n.empty && !h.empty)
2893 {
2894 if (binaryFun!pred(h.front, n.front))
2895 {
2896 h.popFront();
2897 n.popFront();
2898 }
2899 else
2900 {
2901 haystack.popFront();
2902 n = needle.save;
2903 h = haystack.save;
2904 ++pos;
2905 }
2906 }
2907 return Result!(typeof(takeExactly(original, pos)),
2908 typeof(haystack))(takeExactly(original, pos),
2909 haystack);
2910 }
2911}
2912
2913/// Ditto
2914auto findSplitAfter(alias pred = "a == b", R1, R2)(R1 haystack, R2 needle)
2915if (isForwardRange!R1 && isForwardRange!R2)
2916{
2917 static struct Result(S1, S2) if (isForwardRange!S1 &&
2918 isForwardRange!S2)
2919 {
2920 this(S1 pre, S2 post)
2921 {
2922 asTuple = typeof(asTuple)(pre, post);
2923 }
2924 void opAssign(typeof(asTuple) rhs)
2925 {
2926 asTuple = rhs;
2927 }
2928 Tuple!(S1, S2) asTuple;
2929 bool opCast(T : bool)()
2930 {
2931 return !asTuple[1].empty;
2932 }
2933 alias asTuple this;
2934 }
2935
2936 static if (isSomeString!R1 && isSomeString!R2
2937 || isRandomAccessRange!R1 && hasLength!R1 && hasSlicing!R1 && hasLength!R2)
2938 {
2939 auto balance = find!pred(haystack, needle);
2940 immutable pos = balance.empty ? 0 : haystack.length - balance.length + needle.length;
2941 return Result!(typeof(haystack[0 .. pos]),
2942 typeof(haystack[pos .. haystack.length]))(haystack[0 .. pos],
2943 haystack[pos .. haystack.length]);
2944 }
2945 else
2946 {
2947 import std.range : takeExactly;
2948 auto original = haystack.save;
2949 auto h = haystack.save;
2950 auto n = needle.save;
2951 size_t pos1, pos2;
2952 while (!n.empty)
2953 {
2954 if (h.empty)
2955 {
2956 // Failed search
2957 return Result!(typeof(takeExactly(original, 0)),
2958 typeof(original))(takeExactly(original, 0),
2959 original);
2960 }
2961 if (binaryFun!pred(h.front, n.front))
2962 {
2963 h.popFront();
2964 n.popFront();
2965 ++pos2;
2966 }
2967 else
2968 {
2969 haystack.popFront();
2970 n = needle.save;
2971 h = haystack.save;
2972 pos2 = ++pos1;
2973 }
2974 }
2975 return Result!(typeof(takeExactly(original, pos2)),
2976 typeof(h))(takeExactly(original, pos2),
2977 h);
2978 }
2979}
2980
2981///
2982@safe pure nothrow unittest
2983{
2984 import std.range.primitives : empty;
2985
2986 auto a = "Carl Sagan Memorial Station";
2987 auto r = findSplit(a, "Velikovsky");
2988 import std.typecons : isTuple;
2989 static assert(isTuple!(typeof(r.asTuple)));
2990 static assert(isTuple!(typeof(r)));
2991 assert(!r);
2992 assert(r[0] == a);
2993 assert(r[1].empty);
2994 assert(r[2].empty);
2995 r = findSplit(a, " ");
2996 assert(r[0] == "Carl");
2997 assert(r[1] == " ");
2998 assert(r[2] == "Sagan Memorial Station");
2999 auto r1 = findSplitBefore(a, "Sagan");
3000 assert(r1);
3001 assert(r1[0] == "Carl ");
3002 assert(r1[1] == "Sagan Memorial Station");
3003 auto r2 = findSplitAfter(a, "Sagan");
3004 assert(r2);
3005 assert(r2[0] == "Carl Sagan");
3006 assert(r2[1] == " Memorial Station");
3007}
3008
3009/// Use $(REF only, std,range) to find single elements:
3010@safe pure nothrow unittest
3011{
3012 import std.range : only;
3013 assert([1, 2, 3, 4].findSplitBefore(only(3))[0] == [1, 2]);
3014}
3015
3016@safe pure nothrow unittest
3017{
3018 import std.range.primitives : empty;
3019
3020 auto a = [ 1, 2, 3, 4, 5, 6, 7, 8 ];
3021 auto r = findSplit(a, [9, 1]);
3022 assert(!r);
3023 assert(r[0] == a);
3024 assert(r[1].empty);
3025 assert(r[2].empty);
3026 r = findSplit(a, [3]);
3027 assert(r);
3028 assert(r[0] == a[0 .. 2]);
3029 assert(r[1] == a[2 .. 3]);
3030 assert(r[2] == a[3 .. $]);
3031
3032 auto r1 = findSplitBefore(a, [9, 1]);
3033 assert(r1);
3034 assert(r1[0] == a);
3035 assert(r1[1].empty);
3036 r1 = findSplitBefore(a, [3, 4]);
3037 assert(r1);
3038 assert(r1[0] == a[0 .. 2]);
3039 assert(r1[1] == a[2 .. $]);
3040
3041 auto r2 = findSplitAfter(a, [9, 1]);
3042 assert(r2);
3043 assert(r2[0].empty);
3044 assert(r2[1] == a);
3045 r2 = findSplitAfter(a, [3, 4]);
3046 assert(r2);
3047 assert(r2[0] == a[0 .. 4]);
3048 assert(r2[1] == a[4 .. $]);
3049}
3050
3051@safe pure nothrow unittest
3052{
3053 import std.algorithm.comparison : equal;
3054 import std.algorithm.iteration : filter;
3055
3056 auto a = [ 1, 2, 3, 4, 5, 6, 7, 8 ];
3057 auto fwd = filter!"a > 0"(a);
3058 auto r = findSplit(fwd, [9, 1]);
3059 assert(!r);
3060 assert(equal(r[0], a));
3061 assert(r[1].empty);
3062 assert(r[2].empty);
3063 r = findSplit(fwd, [3]);
3064 assert(r);
3065 assert(equal(r[0], a[0 .. 2]));
3066 assert(equal(r[1], a[2 .. 3]));
3067 assert(equal(r[2], a[3 .. $]));
3068
3069 auto r1 = findSplitBefore(fwd, [9, 1]);
3070 assert(r1);
3071 assert(equal(r1[0], a));
3072 assert(r1[1].empty);
3073 r1 = findSplitBefore(fwd, [3, 4]);
3074 assert(r1);
3075 assert(equal(r1[0], a[0 .. 2]));
3076 assert(equal(r1[1], a[2 .. $]));
3077
3078 auto r2 = findSplitAfter(fwd, [9, 1]);
3079 assert(r2);
3080 assert(r2[0].empty);
3081 assert(equal(r2[1], a));
3082 r2 = findSplitAfter(fwd, [3, 4]);
3083 assert(r2);
3084 assert(equal(r2[0], a[0 .. 4]));
3085 assert(equal(r2[1], a[4 .. $]));
3086}
3087
3088@safe pure nothrow @nogc unittest
3089{
3090 auto str = "sep,one,sep,two";
3091
3092 auto split = str.findSplitAfter(",");
3093 assert(split[0] == "sep,");
3094
3095 split = split[1].findSplitAfter(",");
3096 assert(split[0] == "one,");
3097
3098 split = split[1].findSplitBefore(",");
3099 assert(split[0] == "sep");
3100}
3101
3102@safe pure nothrow @nogc unittest
3103{
3104 auto str = "sep,one,sep,two";
3105
3106 auto split = str.findSplitBefore(",two");
3107 assert(split[0] == "sep,one,sep");
3108 assert(split[1] == ",two");
3109
3110 split = split[0].findSplitBefore(",sep");
3111 assert(split[0] == "sep,one");
3112 assert(split[1] == ",sep");
3113
3114 split = split[0].findSplitAfter(",");
3115 assert(split[0] == "sep,");
3116 assert(split[1] == "one");
3117}
3118
3119// minCount
3120/**
3121
3122Computes the minimum (respectively maximum) of `range` along with its number of
3123occurrences. Formally, the minimum is a value `x` in `range` such that $(D
3124pred(a, x)) is `false` for all values `a` in `range`. Conversely, the maximum is
3125a value `x` in `range` such that $(D pred(x, a)) is `false` for all values `a`
3126in `range` (note the swapped arguments to `pred`).
3127
3128These functions may be used for computing arbitrary extrema by choosing `pred`
3129appropriately. For corrrect functioning, `pred` must be a strict partial order,
3130i.e. transitive (if $(D pred(a, b) && pred(b, c)) then $(D pred(a, c))) and
3131irreflexive ($(D pred(a, a)) is `false`). The $(LUCKY trichotomy property of
3132inequality) is not required: these algoritms consider elements `a` and `b` equal
3133(for the purpose of counting) if `pred` puts them in the same equivalence class,
3134i.e. $(D !pred(a, b) && !pred(b, a)).
3135
3136Params:
3137 pred = The ordering predicate to use to determine the extremum (minimum
3138 or maximum).
3139 range = The $(REF_ALTTEXT input range, isInputRange, std,range,primitives) to count.
3140
3141Returns: The minimum, respectively maximum element of a range together with the
3142number it occurs in the range.
3143
3144Throws: `Exception` if `range.empty`.
3145 */
3146Tuple!(ElementType!Range, size_t)
3147minCount(alias pred = "a < b", Range)(Range range)
3148if (isInputRange!Range && !isInfinite!Range &&
3149 is(typeof(binaryFun!pred(range.front, range.front))))
3150{
3151 import std.algorithm.internal : algoFormat;
3152 import std.exception : enforce;
3153
3154 alias T = ElementType!Range;
3155 alias UT = Unqual!T;
3156 alias RetType = Tuple!(T, size_t);
3157
3158 static assert(is(typeof(RetType(range.front, 1))),
3159 algoFormat("Error: Cannot call minCount on a %s, because it is not possible "~
3160 "to copy the result value (a %s) into a Tuple.", Range.stringof, T.stringof));
3161
3162 enforce(!range.empty, "Can't count elements from an empty range");
3163 size_t occurrences = 1;
3164
3165 static if (isForwardRange!Range)
3166 {
3167 Range least = range.save;
3168 for (range.popFront(); !range.empty; range.popFront())
3169 {
3170 if (binaryFun!pred(least.front, range.front))
3171 {
3172 assert(!binaryFun!pred(range.front, least.front),
3173 "min/maxPos: predicate must be a strict partial order.");
3174 continue;
3175 }
3176 if (binaryFun!pred(range.front, least.front))
3177 {
3178 // change the min
3179 least = range.save;
3180 occurrences = 1;
3181 }
3182 else
3183 ++occurrences;
3184 }
3185 return RetType(least.front, occurrences);
3186 }
3187 else static if (isAssignable!(UT, T) || (!hasElaborateAssign!UT && isAssignable!UT))
3188 {
3189 UT v = UT.init;
3190 static if (isAssignable!(UT, T)) v = range.front;
3191 else v = cast(UT) range.front;
3192
3193 for (range.popFront(); !range.empty; range.popFront())
3194 {
3195 if (binaryFun!pred(*cast(T*)&v, range.front)) continue;
3196 if (binaryFun!pred(range.front, *cast(T*)&v))
3197 {
3198 // change the min
3199 static if (isAssignable!(UT, T)) v = range.front;
3200 else v = cast(UT) range.front; //Safe because !hasElaborateAssign!UT
3201 occurrences = 1;
3202 }
3203 else
3204 ++occurrences;
3205 }
3206 return RetType(*cast(T*)&v, occurrences);
3207 }
3208 else static if (hasLvalueElements!Range)
3209 {
3210 import std.algorithm.internal : addressOf;
3211 T* p = addressOf(range.front);
3212 for (range.popFront(); !range.empty; range.popFront())
3213 {
3214 if (binaryFun!pred(*p, range.front)) continue;
3215 if (binaryFun!pred(range.front, *p))
3216 {
3217 // change the min
3218 p = addressOf(range.front);
3219 occurrences = 1;
3220 }
3221 else
3222 ++occurrences;
3223 }
3224 return RetType(*p, occurrences);
3225 }
3226 else
3227 static assert(false,
3228 algoFormat("Sorry, can't find the minCount of a %s: Don't know how "~
3229 "to keep track of the smallest %s element.", Range.stringof, T.stringof));
3230}
3231
3232/// Ditto
3233Tuple!(ElementType!Range, size_t)
3234maxCount(alias pred = "a < b", Range)(Range range)
3235if (isInputRange!Range && !isInfinite!Range &&
3236 is(typeof(binaryFun!pred(range.front, range.front))))
3237{
3238 return range.minCount!((a, b) => binaryFun!pred(b, a));
3239}
3240
3241///
3242@safe unittest
3243{
3244 import std.conv : text;
3245 import std.typecons : tuple;
3246
3247 int[] a = [ 2, 3, 4, 1, 2, 4, 1, 1, 2 ];
3248 // Minimum is 1 and occurs 3 times
3249 assert(a.minCount == tuple(1, 3));
3250 // Maximum is 4 and occurs 2 times
3251 assert(a.maxCount == tuple(4, 2));
3252}
3253
3254@system unittest
3255{
3256 import std.conv : text;
3257 import std.exception : assertThrown;
3258 import std.internal.test.dummyrange;
3259
3260 int[][] b = [ [4], [2, 4], [4], [4] ];
3261 auto c = minCount!("a[0] < b[0]")(b);
3262 assert(c == tuple([2, 4], 1), text(c[0]));
3263
3264 //Test empty range
3265 assertThrown(minCount(b[$..$]));
3266
3267 //test with reference ranges. Test both input and forward.
3268 assert(minCount(new ReferenceInputRange!int([1, 2, 1, 0, 2, 0])) == tuple(0, 2));
3269 assert(minCount(new ReferenceForwardRange!int([1, 2, 1, 0, 2, 0])) == tuple(0, 2));
3270}
3271
3272@system unittest
3273{
3274 import std.conv : text;
3275 import std.meta : AliasSeq;
3276
3277 static struct R(T) //input range
3278 {
3279 T[] arr;
3280 alias arr this;
3281 }
3282
3283 immutable a = [ 2, 3, 4, 1, 2, 4, 1, 1, 2 ];
3284 R!(immutable int) b = R!(immutable int)(a);
3285
3286 assert(minCount(a) == tuple(1, 3));
3287 assert(minCount(b) == tuple(1, 3));
3288 assert(minCount!((ref immutable int a, ref immutable int b) => (a > b))(a) == tuple(4, 2));
3289 assert(minCount!((ref immutable int a, ref immutable int b) => (a > b))(b) == tuple(4, 2));
3290
3291 immutable(int[])[] c = [ [4], [2, 4], [4], [4] ];
3292 assert(minCount!("a[0] < b[0]")(c) == tuple([2, 4], 1), text(c[0]));
3293
3294 static struct S1
3295 {
3296 int i;
3297 }
3298 alias IS1 = immutable(S1);
3299 static assert( isAssignable!S1);
3300 static assert( isAssignable!(S1, IS1));
3301
3302 static struct S2
3303 {
3304 int* p;
3305 this(ref immutable int i) immutable {p = &i;}
3306 this(ref int i) {p = &i;}
3307 @property ref inout(int) i() inout {return *p;}
3308 bool opEquals(const S2 other) const {return i == other.i;}
3309 }
3310 alias IS2 = immutable(S2);
3311 static assert( isAssignable!S2);
3312 static assert(!isAssignable!(S2, IS2));
3313 static assert(!hasElaborateAssign!S2);
3314
3315 static struct S3
3316 {
3317 int i;
3318 void opAssign(ref S3 other) @disable;
3319 }
3320 static assert(!isAssignable!S3);
3321
3322 foreach (Type; AliasSeq!(S1, IS1, S2, IS2, S3))
3323 {
3324 static if (is(Type == immutable)) alias V = immutable int;
3325 else alias V = int;
3326 V one = 1, two = 2;
3327 auto r1 = [Type(two), Type(one), Type(one)];
3328 auto r2 = R!Type(r1);
3329 assert(minCount!"a.i < b.i"(r1) == tuple(Type(one), 2));
3330 assert(minCount!"a.i < b.i"(r2) == tuple(Type(one), 2));
3331 assert(one == 1 && two == 2);
3332 }
3333}
3334
3335/**
3336Iterates the passed range and returns the minimal element.
3337A custom mapping function can be passed to `map`.
3338In other languages this is sometimes called `argmin`.
3339
3340Complexity: O(n)
3341 Exactly `n - 1` comparisons are needed.
3342
3343Params:
3344 map = custom accessor for the comparison key
3345 r = range from which the minimal element will be selected
3346 seed = custom seed to use as initial element
3347
3348Returns: The minimal element of the passed-in range.
3349
3350See_Also:
3351 $(REF min, std,algorithm,comparison)
3352*/
3353auto minElement(alias map, Range)(Range r)
3354if (isInputRange!Range && !isInfinite!Range)
3355{
3356 return extremum!map(r);
3357}
3358
3359/// ditto
3360auto minElement(Range)(Range r)
3361 if (isInputRange!Range && !isInfinite!Range)
3362{
3363 return extremum(r);
3364}
3365
3366/// ditto
3367auto minElement(alias map, Range, RangeElementType = ElementType!Range)
3368 (Range r, RangeElementType seed)
3369if (isInputRange!Range && !isInfinite!Range &&
3370 !is(CommonType!(ElementType!Range, RangeElementType) == void))
3371{
3372 return extremum!map(r, seed);
3373}
3374
3375/// ditto
3376auto minElement(Range, RangeElementType = ElementType!Range)
3377 (Range r, RangeElementType seed)
3378 if (isInputRange!Range && !isInfinite!Range &&
3379 !is(CommonType!(ElementType!Range, RangeElementType) == void))
3380{
3381 return extremum(r, seed);
3382}
3383
3384///
3385@safe pure unittest
3386{
3387 import std.range : enumerate;
3388 import std.typecons : tuple;
3389
3390 assert([2, 1, 4, 3].minElement == 1);
3391
3392 // allows to get the index of an element too
3393 assert([5, 3, 7, 9].enumerate.minElement!"a.value" == tuple(1, 3));
3394
3395 // any custom accessor can be passed
3396 assert([[0, 4], [1, 2]].minElement!"a[1]" == [1, 2]);
3397
3398 // can be seeded
3399 int[] arr;
3400 assert(arr.minElement(1) == 1);
3401}
3402
3403@safe pure unittest
3404{
3405 import std.range : enumerate, iota;
3406 // supports mapping
3407 assert([3, 4, 5, 1, 2].enumerate.minElement!"a.value" == tuple(3, 1));
3408 assert([5, 2, 4].enumerate.minElement!"a.value" == tuple(1, 2));
3409
3410 // forward ranges
3411 assert(iota(1, 5).minElement() == 1);
3412 assert(iota(2, 5).enumerate.minElement!"a.value" == tuple(0, 2));
3413
3414 // should work with const
3415 const(int)[] immArr = [2, 1, 3];
3416 assert(immArr.minElement == 1);
3417
3418 // should work with immutable
3419 immutable(int)[] immArr2 = [2, 1, 3];
3420 assert(immArr2.minElement == 1);
3421
3422 // with strings
3423 assert(["b", "a", "c"].minElement == "a");
3424
3425 // with all dummy ranges
3426 import std.internal.test.dummyrange;
3427 foreach (DummyType; AllDummyRanges)
3428 {
3429 DummyType d;
3430 assert(d.minElement == 1);
3431 assert(d.minElement!(a => a) == 1);
3432 }
3433
3434 // with empty, but seeded ranges
3435 int[] arr;
3436 assert(arr.minElement(42) == 42);
3437 assert(arr.minElement!(a => a)(42) == 42);
3438}
3439
3440@nogc @safe nothrow pure unittest
3441{
3442 static immutable arr = [7, 3, 4, 2, 1, 8];
3443 assert(arr.minElement == 1);
3444
3445 static immutable arr2d = [[1, 9], [3, 1], [4, 2]];
3446 assert(arr2d.minElement!"a[1]" == arr2d[1]);
3447}
3448
3449/**
3450Iterates the passed range and returns the maximal element.
3451A custom mapping function can be passed to `map`.
3452In other languages this is sometimes called `argmax`.
3453
3454Complexity:
3455 Exactly `n - 1` comparisons are needed.
3456
3457Params:
3458 map = custom accessor for the comparison key
3459 r = range from which the maximum will be selected
3460 seed = custom seed to use as initial element
3461
3462Returns: The maximal element of the passed-in range.
3463
3464See_Also:
3465 $(REF max, std,algorithm,comparison)
3466*/
3467auto maxElement(alias map, Range)(Range r)
3468if (isInputRange!Range && !isInfinite!Range)
3469{
3470 return extremum!(map, "a > b")(r);
3471}
3472
3473/// ditto
3474auto maxElement(Range)(Range r)
3475if (isInputRange!Range && !isInfinite!Range)
3476{
3477 return extremum!`a > b`(r);
3478}
3479
3480/// ditto
3481auto maxElement(alias map, Range, RangeElementType = ElementType!Range)
3482 (Range r, RangeElementType seed)
3483if (isInputRange!Range && !isInfinite!Range &&
3484 !is(CommonType!(ElementType!Range, RangeElementType) == void))
3485{
3486 return extremum!(map, "a > b")(r, seed);
3487}
3488
3489/// ditto
3490auto maxElement(Range, RangeElementType = ElementType!Range)
3491 (Range r, RangeElementType seed)
3492if (isInputRange!Range && !isInfinite!Range &&
3493 !is(CommonType!(ElementType!Range, RangeElementType) == void))
3494{
3495 return extremum!`a > b`(r, seed);
3496}
3497
3498///
3499@safe pure unittest
3500{
3501 import std.range : enumerate;
3502 import std.typecons : tuple;
3503 assert([2, 1, 4, 3].maxElement == 4);
3504
3505 // allows to get the index of an element too
3506 assert([2, 1, 4, 3].enumerate.maxElement!"a.value" == tuple(2, 4));
3507
3508 // any custom accessor can be passed
3509 assert([[0, 4], [1, 2]].maxElement!"a[1]" == [0, 4]);
3510
3511 // can be seeded
3512 int[] arr;
3513 assert(arr.minElement(1) == 1);
3514}
3515
3516@safe pure unittest
3517{
3518 import std.range : enumerate, iota;
3519
3520 // supports mapping
3521 assert([3, 4, 5, 1, 2].enumerate.maxElement!"a.value" == tuple(2, 5));
3522 assert([5, 2, 4].enumerate.maxElement!"a.value" == tuple(0, 5));
3523
3524 // forward ranges
3525 assert(iota(1, 5).maxElement() == 4);
3526 assert(iota(2, 5).enumerate.maxElement!"a.value" == tuple(2, 4));
3527 assert(iota(4, 14).enumerate.maxElement!"a.value" == tuple(9, 13));
3528
3529 // should work with const
3530 const(int)[] immArr = [2, 3, 1];
3531 assert(immArr.maxElement == 3);
3532
3533 // should work with immutable
3534 immutable(int)[] immArr2 = [2, 3, 1];
3535 assert(immArr2.maxElement == 3);
3536
3537 // with strings
3538 assert(["a", "c", "b"].maxElement == "c");
3539
3540 // with all dummy ranges
3541 import std.internal.test.dummyrange;
3542 foreach (DummyType; AllDummyRanges)
3543 {
3544 DummyType d;
3545 assert(d.maxElement == 10);
3546 assert(d.maxElement!(a => a) == 10);
3547 }
3548
3549 // with empty, but seeded ranges
3550 int[] arr;
3551 assert(arr.maxElement(42) == 42);
3552 assert(arr.maxElement!(a => a)(42) == 42);
3553
3554}
3555
3556@nogc @safe nothrow pure unittest
3557{
3558 static immutable arr = [7, 3, 8, 2, 1, 4];
3559 assert(arr.maxElement == 8);
3560
3561 static immutable arr2d = [[1, 3], [3, 9], [4, 2]];
3562 assert(arr2d.maxElement!"a[1]" == arr2d[1]);
3563}
3564
3565// minPos
3566/**
3567Computes a subrange of `range` starting at the first occurrence of `range`'s
3568minimum (respectively maximum) and with the same ending as `range`, or the
3569empty range if `range` itself is empty.
3570
3571Formally, the minimum is a value `x` in `range` such that $(D pred(a, x)) is
3572`false` for all values `a` in `range`. Conversely, the maximum is a value `x` in
3573`range` such that $(D pred(x, a)) is `false` for all values `a` in `range` (note
3574the swapped arguments to `pred`).
3575
3576These functions may be used for computing arbitrary extrema by choosing `pred`
3577appropriately. For corrrect functioning, `pred` must be a strict partial order,
3578i.e. transitive (if $(D pred(a, b) && pred(b, c)) then $(D pred(a, c))) and
3579irreflexive ($(D pred(a, a)) is `false`).
3580
3581Params:
3582 pred = The ordering predicate to use to determine the extremum (minimum or
3583 maximum) element.
3584 range = The $(REF_ALTTEXT input range, isInputRange, std,range,primitives) to search.
3585
3586Returns: The position of the minimum (respectively maximum) element of forward
3587range `range`, i.e. a subrange of `range` starting at the position of its
3588smallest (respectively largest) element and with the same ending as `range`.
3589
3590*/
3591Range minPos(alias pred = "a < b", Range)(Range range)
3592if (isForwardRange!Range && !isInfinite!Range &&
3593 is(typeof(binaryFun!pred(range.front, range.front))))
3594{
3595 static if (hasSlicing!Range && isRandomAccessRange!Range && hasLength!Range)
3596 {
3597 // Prefer index-based access
3598 size_t pos = 0;
3599 foreach (i; 1 .. range.length)
3600 {
3601 if (binaryFun!pred(range[i], range[pos]))
3602 {
3603 pos = i;
3604 }
3605 }
3606 return range[pos .. range.length];
3607 }
3608 else
3609 {
3610 auto result = range.save;
3611 if (range.empty) return result;
3612 for (range.popFront(); !range.empty; range.popFront())
3613 {
3614 // Note: Unlike minCount, we do not care to find equivalence, so a
3615 // single pred call is enough.
3616 if (binaryFun!pred(range.front, result.front))
3617 {
3618 // change the min
3619 result = range.save;
3620 }
3621 }
3622 return result;
3623 }
3624}
3625
3626/// Ditto
3627Range maxPos(alias pred = "a < b", Range)(Range range)
3628if (isForwardRange!Range && !isInfinite!Range &&
3629 is(typeof(binaryFun!pred(range.front, range.front))))
3630{
3631 return range.minPos!((a, b) => binaryFun!pred(b, a));
3632}
3633
3634///
3635@safe unittest
3636{
3637 int[] a = [ 2, 3, 4, 1, 2, 4, 1, 1, 2 ];
3638 // Minimum is 1 and first occurs in position 3
3639 assert(a.minPos == [ 1, 2, 4, 1, 1, 2 ]);
3640 // Maximum is 4 and first occurs in position 2
3641 assert(a.maxPos == [ 4, 1, 2, 4, 1, 1, 2 ]);
3642}
3643
3644@safe unittest
3645{
3646 import std.algorithm.comparison : equal;
3647 import std.internal.test.dummyrange;
3648
3649 int[] a = [ 2, 3, 4, 1, 2, 4, 1, 1, 2 ];
3650 //Test that an empty range works
3651 int[] b = a[$..$];
3652 assert(equal(minPos(b), b));
3653
3654 //test with reference range.
3655 assert( equal( minPos(new ReferenceForwardRange!int([1, 2, 1, 0, 2, 0])), [0, 2, 0] ) );
3656}
3657
3658@system unittest
3659{
3660 //Rvalue range
3661 import std.algorithm.comparison : equal;
3662 import std.container : Array;
3663
3664 assert(Array!int(2, 3, 4, 1, 2, 4, 1, 1, 2)
3665 []
3666 .minPos()
3667 .equal([ 1, 2, 4, 1, 1, 2 ]));
3668}
3669
3670@safe unittest
3671{
3672 //BUG 9299
3673 immutable a = [ 2, 3, 4, 1, 2, 4, 1, 1, 2 ];
3674 // Minimum is 1 and first occurs in position 3
3675 assert(minPos(a) == [ 1, 2, 4, 1, 1, 2 ]);
3676 // Maximum is 4 and first occurs in position 5
3677 assert(minPos!("a > b")(a) == [ 4, 1, 2, 4, 1, 1, 2 ]);
3678
3679 immutable(int[])[] b = [ [4], [2, 4], [4], [4] ];
3680 assert(minPos!("a[0] < b[0]")(b) == [ [2, 4], [4], [4] ]);
3681}
3682
3683/**
3684Computes the index of the first occurrence of `range`'s minimum element.
3685
3686Params:
3687 pred = The ordering predicate to use to determine the minimum element.
3688 range = The $(REF_ALTTEXT input range, isInputRange, std,range,primitives)
3689 to search.
3690
3691Complexity: O(n)
3692 Exactly `n - 1` comparisons are needed.
3693
3694Returns:
3695 The index of the first encounter of the minimum element in `range`. If the
3696 `range` is empty, -1 is returned.
3697
3698See_Also:
3699 $(REF min, std,algorithm,comparison), $(LREF minCount), $(LREF minElement), $(LREF minPos)
3700 */
3701sizediff_t minIndex(alias pred = "a < b", Range)(Range range)
3702if (isForwardRange!Range && !isInfinite!Range &&
3703 is(typeof(binaryFun!pred(range.front, range.front))))
3704{
3705 if (range.empty) return -1;
3706
3707 sizediff_t minPos = 0;
3708
3709 static if (isRandomAccessRange!Range && hasLength!Range)
3710 {
3711 foreach (i; 1 .. range.length)
3712 {
3713 if (binaryFun!pred(range[i], range[minPos]))
3714 {
3715 minPos = i;
3716 }
3717 }
3718 }
3719 else
3720 {
3721 sizediff_t curPos = 0;
3722 Unqual!(typeof(range.front)) min = range.front;
3723 for (range.popFront(); !range.empty; range.popFront())
3724 {
3725 ++curPos;
3726 if (binaryFun!pred(range.front, min))
3727 {
3728 min = range.front;
3729 minPos = curPos;
3730 }
3731 }
3732 }
3733 return minPos;
3734}
3735
3736///
3737@safe pure nothrow unittest
3738{
3739 int[] a = [2, 3, 4, 1, 2, 4, 1, 1, 2];
3740
3741 // Minimum is 1 and first occurs in position 3
3742 assert(a.minIndex == 3);
3743 // Get maximum index with minIndex
3744 assert(a.minIndex!"a > b" == 2);
3745
3746 // Range is empty, so return value is -1
3747 int[] b;
3748 assert(b.minIndex == -1);
3749
3750 // Works with more custom types
3751 struct Dog { int age; }
3752 Dog[] dogs = [Dog(10), Dog(5), Dog(15)];
3753 assert(dogs.minIndex!"a.age < b.age" == 1);
3754}
3755
3756@safe pure unittest
3757{
3758 // should work with const
3759 const(int)[] immArr = [2, 1, 3];
3760 assert(immArr.minIndex == 1);
3761
3762 // Works for const ranges too
3763 const int[] c = [2, 5, 4, 1, 2, 3];
3764 assert(c.minIndex == 3);
3765
3766 // should work with immutable
3767 immutable(int)[] immArr2 = [2, 1, 3];
3768 assert(immArr2.minIndex == 1);
3769
3770 // with strings
3771 assert(["b", "a", "c"].minIndex == 1);
3772
3773 // infinite range
3774 import std.range : cycle;
3775 static assert(!__traits(compiles, cycle([1]).minIndex));
3776
3777 // with all dummy ranges
3778 import std.internal.test.dummyrange : AllDummyRanges;
3779 foreach (DummyType; AllDummyRanges)
3780 {
3781 static if (isForwardRange!DummyType && !isInfinite!DummyType)
3782 {
3783 DummyType d;
3784 d.arr = [5, 3, 7, 2, 1, 4];
3785 assert(d.minIndex == 4);
3786
3787 d.arr = [];
3788 assert(d.minIndex == -1);
3789 }
3790 }
3791}
3792
3793@nogc @safe nothrow pure unittest
3794{
3795 static immutable arr = [7, 3, 8, 2, 1, 4];
3796 assert(arr.minIndex == 4);
3797
3798 static immutable arr2d = [[1, 3], [3, 9], [4, 2]];
3799 assert(arr2d.minIndex!"a[1] < b[1]" == 2);
3800}
3801
3802/**
3803Computes the index of the first occurrence of `range`'s maximum element.
3804
3805Complexity: O(n)
3806 Exactly `n - 1` comparisons are needed.
3807
3808Params:
3809 pred = The ordering predicate to use to determine the maximum element.
3810 range = The $(REF_ALTTEXT input range, isInputRange, std,range,primitives) to search.
3811
3812Returns:
3813 The index of the first encounter of the maximum in `range`. If the
3814 `range` is empty, -1 is returned.
3815
3816See_Also:
3817 $(REF max, std,algorithm,comparison), $(LREF maxCount), $(LREF maxElement), $(LREF maxPos)
3818 */
3819sizediff_t maxIndex(alias pred = "a < b", Range)(Range range)
3820if (isInputRange!Range && !isInfinite!Range &&
3821 is(typeof(binaryFun!pred(range.front, range.front))))
3822{
3823 return range.minIndex!((a, b) => binaryFun!pred(b, a));
3824}
3825
3826///
3827@safe pure nothrow unittest
3828{
3829 // Maximum is 4 and first occurs in position 2
3830 int[] a = [2, 3, 4, 1, 2, 4, 1, 1, 2];
3831 assert(a.maxIndex == 2);
3832
3833 // Empty range
3834 int[] b;
3835 assert(b.maxIndex == -1);
3836
3837 // Works with more custom types
3838 struct Dog { int age; }
3839 Dog[] dogs = [Dog(10), Dog(15), Dog(5)];
3840 assert(dogs.maxIndex!"a.age < b.age" == 1);
3841}
3842
3843@safe pure unittest
3844{
3845 // should work with const
3846 const(int)[] immArr = [5, 1, 3];
3847 assert(immArr.maxIndex == 0);
3848
3849 // Works for const ranges too
3850 const int[] c = [2, 5, 4, 1, 2, 3];
3851 assert(c.maxIndex == 1);
3852
3853
3854 // should work with immutable
3855 immutable(int)[] immArr2 = [2, 1, 3];
3856 assert(immArr2.maxIndex == 2);
3857
3858 // with strings
3859 assert(["b", "a", "c"].maxIndex == 2);
3860
3861 // infinite range
3862 import std.range : cycle;
3863 static assert(!__traits(compiles, cycle([1]).maxIndex));
3864
3865 // with all dummy ranges
3866 import std.internal.test.dummyrange : AllDummyRanges;
3867 foreach (DummyType; AllDummyRanges)
3868 {
3869 static if (isForwardRange!DummyType && !isInfinite!DummyType)
3870 {
3871 DummyType d;
3872
3873 d.arr = [5, 3, 7, 2, 1, 4];
3874 assert(d.maxIndex == 2);
3875
3876 d.arr = [];
3877 assert(d.maxIndex == -1);
3878 }
3879 }
3880}
3881
3882@nogc @safe nothrow pure unittest
3883{
3884 static immutable arr = [7, 3, 8, 2, 1, 4];
3885 assert(arr.maxIndex == 2);
3886
3887 static immutable arr2d = [[1, 3], [3, 9], [4, 2]];
3888 assert(arr2d.maxIndex!"a[1] < b[1]" == 1);
3889}
3890
3891/**
3892Skip over the initial portion of the first given range that matches the second
3893range, or if no second range is given skip over the elements that fullfil pred.
3894Do nothing if there is no match.
3895
3896Params:
3897 pred = The predicate that determines whether elements from each respective
3898 range match. Defaults to equality $(D "a == b").
3899 r1 = The $(REF_ALTTEXT forward range, isForwardRange, std,range,primitives) to
3900 move forward.
3901 r2 = The $(REF_ALTTEXT input range, isInputRange, std,range,primitives)
3902 representing the initial segment of $(D r1) to skip over.
3903
3904Returns:
3905true if the initial segment of $(D r1) matches $(D r2) or $(D pred) evaluates to true,
3906and $(D r1) has been advanced to the point past this segment; otherwise false, and
3907$(D r1) is left in its original position.
3908 */
3909bool skipOver(R1, R2)(ref R1 r1, R2 r2)
3910if (isForwardRange!R1 && isInputRange!R2
3911 && is(typeof(r1.front == r2.front)))
3912{
3913 static if (is(typeof(r1[0 .. $] == r2) : bool)
3914 && is(typeof(r2.length > r1.length) : bool)
3915 && is(typeof(r1 = r1[r2.length .. $])))
3916 {
3917 if (r2.length > r1.length || r1[0 .. r2.length] != r2)
3918 {
3919 return false;
3920 }
3921 r1 = r1[r2.length .. $];
3922 return true;
3923 }
3924 else
3925 {
3926 return skipOver!((a, b) => a == b)(r1, r2);
3927 }
3928}
3929
3930/// Ditto
3931bool skipOver(alias pred, R1, R2)(ref R1 r1, R2 r2)
3932if (is(typeof(binaryFun!pred(r1.front, r2.front))) &&
3933 isForwardRange!R1 &&
3934 isInputRange!R2)
3935{
3936 static if (hasLength!R1 && hasLength!R2)
3937 {
3938 // Shortcut opportunity!
3939 if (r2.length > r1.length)
3940 return false;
3941 }
3942 auto r = r1.save;
3943 while (!r2.empty && !r.empty && binaryFun!pred(r.front, r2.front))
3944 {
3945 r.popFront();
3946 r2.popFront();
3947 }
3948 if (r2.empty)
3949 r1 = r;
3950 return r2.empty;
3951}
3952
3953/// Ditto
3954bool skipOver(alias pred, R)(ref R r1)
3955if (isForwardRange!R &&
3956 ifTestable!(typeof(r1.front), unaryFun!pred))
3957{
3958 if (r1.empty || !unaryFun!pred(r1.front))
3959 return false;
3960
3961 do
3962 r1.popFront();
3963 while (!r1.empty && unaryFun!pred(r1.front));
3964 return true;
3965}
3966
3967///
3968@safe unittest
3969{
3970 import std.algorithm.comparison : equal;
3971
3972 auto s1 = "Hello world";
3973 assert(!skipOver(s1, "Ha"));
3974 assert(s1 == "Hello world");
3975 assert(skipOver(s1, "Hell") && s1 == "o world");
3976
3977 string[] r1 = ["abc", "def", "hij"];
3978 dstring[] r2 = ["abc"d];
3979 assert(!skipOver!((a, b) => a.equal(b))(r1, ["def"d]));
3980 assert(r1 == ["abc", "def", "hij"]);
3981 assert(skipOver!((a, b) => a.equal(b))(r1, r2));
3982 assert(r1 == ["def", "hij"]);
3983
3984 import std.ascii : isWhite;
3985 import std.range.primitives : empty;
3986
3987 auto s2 = "\t\tvalue";
3988 auto s3 = "";
3989 auto s4 = "\t\t\t";
3990 assert(s2.skipOver!isWhite && s2 == "value");
3991 assert(!s3.skipOver!isWhite);
3992 assert(s4.skipOver!isWhite && s3.empty);
3993}
3994
3995/**
3996Skip over the first element of the given range if it matches the given element,
3997otherwise do nothing.
3998
3999Params:
4000 pred = The predicate that determines whether an element from the range
4001 matches the given element.
4002
4003 r = The $(REF_ALTTEXT input range, isInputRange, std,range,primitives) to skip
4004 over.
4005
4006 e = The element to match.
4007
4008Returns:
4009true if the first element matches the given element according to the given
4010predicate, and the range has been advanced by one element; otherwise false, and
4011the range is left untouched.
4012 */
4013bool skipOver(R, E)(ref R r, E e)
4014if (isInputRange!R && is(typeof(r.front == e) : bool))
4015{
4016 return skipOver!((a, b) => a == b)(r, e);
4017}
4018
4019/// Ditto
4020bool skipOver(alias pred, R, E)(ref R r, E e)
4021if (is(typeof(binaryFun!pred(r.front, e))) && isInputRange!R)
4022{
4023 if (r.empty || !binaryFun!pred(r.front, e))
4024 return false;
4025 r.popFront();
4026 return true;
4027}
4028
4029///
4030@safe unittest
4031{
4032 import std.algorithm.comparison : equal;
4033
4034 auto s1 = "Hello world";
4035 assert(!skipOver(s1, 'a'));
4036 assert(s1 == "Hello world");
4037 assert(skipOver(s1, 'H') && s1 == "ello world");
4038
4039 string[] r = ["abc", "def", "hij"];
4040 dstring e = "abc"d;
4041 assert(!skipOver!((a, b) => a.equal(b))(r, "def"d));
4042 assert(r == ["abc", "def", "hij"]);
4043 assert(skipOver!((a, b) => a.equal(b))(r, e));
4044 assert(r == ["def", "hij"]);
4045
4046 auto s2 = "";
4047 assert(!s2.skipOver('a'));
4048}
4049
4050/**
4051Checks whether the given
4052$(REF_ALTTEXT input range, isInputRange, std,range,primitives) starts with (one
4053of) the given needle(s) or, if no needles are given,
4054if its front element fulfils predicate $(D pred).
4055
4056Params:
4057
4058 pred = Predicate to use in comparing the elements of the haystack and the
4059 needle(s). Mandatory if no needles are given.
4060
4061 doesThisStart = The input range to check.
4062
4063 withOneOfThese = The needles against which the range is to be checked,
4064 which may be individual elements or input ranges of elements.
4065
4066 withThis = The single needle to check, which may be either a single element
4067 or an input range of elements.
4068
4069Returns:
4070
40710 if the needle(s) do not occur at the beginning of the given range;
4072otherwise the position of the matching needle, that is, 1 if the range starts
4073with $(D withOneOfThese[0]), 2 if it starts with $(D withOneOfThese[1]), and so
4074on.
4075
4076In the case where $(D doesThisStart) starts with multiple of the ranges or
4077elements in $(D withOneOfThese), then the shortest one matches (if there are
4078two which match which are of the same length (e.g. $(D "a") and $(D 'a')), then
4079the left-most of them in the argument
4080list matches).
4081
4082In the case when no needle parameters are given, return $(D true) iff front of
4083$(D doesThisStart) fulfils predicate $(D pred).
4084 */
4085uint startsWith(alias pred = "a == b", Range, Needles...)(Range doesThisStart, Needles withOneOfThese)
4086if (isInputRange!Range && Needles.length > 1 &&
4087 is(typeof(.startsWith!pred(doesThisStart, withOneOfThese[0])) : bool ) &&
4088 is(typeof(.startsWith!pred(doesThisStart, withOneOfThese[1 .. $])) : uint))
4089{
4090 alias haystack = doesThisStart;
4091 alias needles = withOneOfThese;
4092
4093 // Make one pass looking for empty ranges in needles
4094 foreach (i, Unused; Needles)
4095 {
4096 // Empty range matches everything
4097 static if (!is(typeof(binaryFun!pred(haystack.front, needles[i])) : bool))
4098 {
4099 if (needles[i].empty) return i + 1;
4100 }
4101 }
4102
4103 for (; !haystack.empty; haystack.popFront())
4104 {
4105 foreach (i, Unused; Needles)
4106 {
4107 static if (is(typeof(binaryFun!pred(haystack.front, needles[i])) : bool))
4108 {
4109 // Single-element
4110 if (binaryFun!pred(haystack.front, needles[i]))
4111 {
4112 // found, but instead of returning, we just stop searching.
4113 // This is to account for one-element
4114 // range matches (consider startsWith("ab", "a",
4115 // 'a') should return 1, not 2).
4116 break;
4117 }
4118 }
4119 else
4120 {
4121 if (binaryFun!pred(haystack.front, needles[i].front))
4122 {
4123 continue;
4124 }
4125 }
4126
4127 // This code executed on failure to match
4128 // Out with this guy, check for the others
4129 uint result = startsWith!pred(haystack, needles[0 .. i], needles[i + 1 .. $]);
4130 if (result > i) ++result;
4131 return result;
4132 }
4133
4134 // If execution reaches this point, then the front matches for all
4135 // needle ranges, or a needle element has been matched.
4136 // What we need to do now is iterate, lopping off the front of
4137 // the range and checking if the result is empty, or finding an
4138 // element needle and returning.
4139 // If neither happens, we drop to the end and loop.
4140 foreach (i, Unused; Needles)
4141 {
4142 static if (is(typeof(binaryFun!pred(haystack.front, needles[i])) : bool))
4143 {
4144 // Test has passed in the previous loop
4145 return i + 1;
4146 }
4147 else
4148 {
4149 needles[i].popFront();
4150 if (needles[i].empty) return i + 1;
4151 }
4152 }
4153 }
4154 return 0;
4155}
4156
4157/// Ditto
4158bool startsWith(alias pred = "a == b", R1, R2)(R1 doesThisStart, R2 withThis)
4159if (isInputRange!R1 &&
4160 isInputRange!R2 &&
4161 is(typeof(binaryFun!pred(doesThisStart.front, withThis.front)) : bool))
4162{
4163 alias haystack = doesThisStart;
4164 alias needle = withThis;
4165
4166 static if (is(typeof(pred) : string))
4167 enum isDefaultPred = pred == "a == b";
4168 else
4169 enum isDefaultPred = false;
4170
4171 //Note: While narrow strings don't have a "true" length, for a narrow string to start with another
4172 //narrow string *of the same type*, it must have *at least* as many code units.
4173 static if ((hasLength!R1 && hasLength!R2) ||
4174 (isNarrowString!R1 && isNarrowString!R2 && ElementEncodingType!R1.sizeof == ElementEncodingType!R2.sizeof))
4175 {
4176 if (haystack.length < needle.length)
4177 return false;
4178 }
4179
4180 static if (isDefaultPred && isArray!R1 && isArray!R2 &&
4181 is(Unqual!(ElementEncodingType!R1) == Unqual!(ElementEncodingType!R2)))
4182 {
4183 //Array slice comparison mode
4184 return haystack[0 .. needle.length] == needle;
4185 }
4186 else static if (isRandomAccessRange!R1 && isRandomAccessRange!R2 && hasLength!R2)
4187 {
4188 //RA dual indexing mode
4189 foreach (j; 0 .. needle.length)
4190 {
4191 if (!binaryFun!pred(haystack[j], needle[j]))
4192 // not found
4193 return false;
4194 }
4195 // found!
4196 return true;
4197 }
4198 else
4199 {
4200 //Standard input range mode
4201 if (needle.empty) return true;
4202 static if (hasLength!R1 && hasLength!R2)
4203 {
4204 //We have previously checked that haystack.length > needle.length,
4205 //So no need to check haystack.empty during iteration
4206 for ( ; ; haystack.popFront() )
4207 {
4208 if (!binaryFun!pred(haystack.front, needle.front)) break;
4209 needle.popFront();
4210 if (needle.empty) return true;
4211 }
4212 }
4213 else
4214 {
4215 for ( ; !haystack.empty ; haystack.popFront() )
4216 {
4217 if (!binaryFun!pred(haystack.front, needle.front)) break;
4218 needle.popFront();
4219 if (needle.empty) return true;
4220 }
4221 }
4222 return false;
4223 }
4224}
4225
4226/// Ditto
4227bool startsWith(alias pred = "a == b", R, E)(R doesThisStart, E withThis)
4228if (isInputRange!R &&
4229 is(typeof(binaryFun!pred(doesThisStart.front, withThis)) : bool))
4230{
4231 if (doesThisStart.empty)
4232 return false;
4233
4234 alias predFunc = binaryFun!pred;
4235
4236 // auto-decoding special case
4237 static if (isNarrowString!R)
4238 {
4239 // specialize for ASCII as to not change previous behavior
4240 if (withThis <= 0x7F)
4241 return predFunc(doesThisStart[0], withThis);
4242 else
4243 return predFunc(doesThisStart.front, withThis);
4244 }
4245 else
4246 {
4247 return predFunc(doesThisStart.front, withThis);
4248 }
4249}
4250
4251/// Ditto
4252bool startsWith(alias pred, R)(R doesThisStart)
4253if (isInputRange!R &&
4254 ifTestable!(typeof(doesThisStart.front), unaryFun!pred))
4255{
4256 return !doesThisStart.empty && unaryFun!pred(doesThisStart.front);
4257}
4258
4259///
4260@safe unittest
4261{
4262 import std.ascii : isAlpha;
4263
4264 assert("abc".startsWith!(a => a.isAlpha));
4265 assert("abc".startsWith!isAlpha);
4266 assert(!"1ab".startsWith!(a => a.isAlpha));
4267 assert(!"".startsWith!(a => a.isAlpha));
4268
4269 import std.algorithm.comparison : among;
4270 assert("abc".startsWith!(a => a.among('a', 'b') != 0));
4271 assert(!"abc".startsWith!(a => a.among('b', 'c') != 0));
4272
4273 assert(startsWith("abc", ""));
4274 assert(startsWith("abc", "a"));
4275 assert(!startsWith("abc", "b"));
4276 assert(startsWith("abc", 'a', "b") == 1);
4277 assert(startsWith("abc", "b", "a") == 2);
4278 assert(startsWith("abc", "a", "a") == 1);
4279 assert(startsWith("abc", "ab", "a") == 2);
4280 assert(startsWith("abc", "x", "a", "b") == 2);
4281 assert(startsWith("abc", "x", "aa", "ab") == 3);
4282 assert(startsWith("abc", "x", "aaa", "sab") == 0);
4283 assert(startsWith("abc", "x", "aaa", "a", "sab") == 3);
4284
4285 import std.typecons : Tuple;
4286 alias C = Tuple!(int, "x", int, "y");
4287 assert(startsWith!"a.x == b"([ C(1,1), C(1,2), C(2,2) ], [1, 1]));
4288 assert(startsWith!"a.x == b"([ C(1,1), C(2,1), C(2,2) ], [1, 1], [1, 2], [1, 3]) == 2);
4289}
4290
4291@safe unittest
4292{
4293 import std.algorithm.iteration : filter;
4294 import std.conv : to;
4295 import std.meta : AliasSeq;
4296 import std.range;
4297
4298 foreach (S; AliasSeq!(char[], wchar[], dchar[], string, wstring, dstring))
4299 {
4300 assert(!startsWith(to!S("abc"), 'c'));
4301 assert(startsWith(to!S("abc"), 'a', 'c') == 1);
4302 assert(!startsWith(to!S("abc"), 'x', 'n', 'b'));
4303 assert(startsWith(to!S("abc"), 'x', 'n', 'a') == 3);
4304 assert(startsWith(to!S("\uFF28abc"), 'a', '\uFF28', 'c') == 2);
4305
4306 foreach (T; AliasSeq!(char[], wchar[], dchar[], string, wstring, dstring))
4307 (){ // avoid slow optimizations for large functions @@@BUG@@@ 2396
4308 //Lots of strings
4309 assert(startsWith(to!S("abc"), to!T("")));
4310 assert(startsWith(to!S("ab"), to!T("a")));
4311 assert(startsWith(to!S("abc"), to!T("a")));
4312 assert(!startsWith(to!S("abc"), to!T("b")));
4313 assert(!startsWith(to!S("abc"), to!T("b"), "bc", "abcd", "xyz"));
4314 assert(startsWith(to!S("abc"), to!T("ab"), 'a') == 2);
4315 assert(startsWith(to!S("abc"), to!T("a"), "b") == 1);
4316 assert(startsWith(to!S("abc"), to!T("b"), "a") == 2);
4317 assert(startsWith(to!S("abc"), to!T("a"), 'a') == 1);
4318 assert(startsWith(to!S("abc"), 'a', to!T("a")) == 1);
4319 assert(startsWith(to!S("abc"), to!T("x"), "a", "b") == 2);
4320 assert(startsWith(to!S("abc"), to!T("x"), "aa", "ab") == 3);
4321 assert(startsWith(to!S("abc"), to!T("x"), "aaa", "sab") == 0);
4322 assert(startsWith(to!S("abc"), 'a'));
4323 assert(!startsWith(to!S("abc"), to!T("sab")));
4324 assert(startsWith(to!S("abc"), 'x', to!T("aaa"), 'a', "sab") == 3);
4325
4326 //Unicode
4327 assert(startsWith(to!S("\uFF28el\uFF4co"), to!T("\uFF28el")));
4328 assert(startsWith(to!S("\uFF28el\uFF4co"), to!T("Hel"), to!T("\uFF28el")) == 2);
4329 assert(startsWith(to!S("日本語"), to!T("日本")));
4330 assert(startsWith(to!S("日本語"), to!T("日本語")));
4331 assert(!startsWith(to!S("日本"), to!T("日本語")));
4332
4333 //Empty
4334 assert(startsWith(to!S(""), T.init));
4335 assert(!startsWith(to!S(""), 'a'));
4336 assert(startsWith(to!S("a"), T.init));
4337 assert(startsWith(to!S("a"), T.init, "") == 1);
4338 assert(startsWith(to!S("a"), T.init, 'a') == 1);
4339 assert(startsWith(to!S("a"), 'a', T.init) == 2);
4340 }();
4341 }
4342
4343 //Length but no RA
4344 assert(!startsWith("abc".takeExactly(3), "abcd".takeExactly(4)));
4345 assert(startsWith("abc".takeExactly(3), "abcd".takeExactly(3)));
4346 assert(startsWith("abc".takeExactly(3), "abcd".takeExactly(1)));
4347
4348 foreach (T; AliasSeq!(int, short))
4349 {
4350 immutable arr = cast(T[])[0, 1, 2, 3, 4, 5];
4351
4352 //RA range
4353 assert(startsWith(arr, cast(int[]) null));
4354 assert(!startsWith(arr, 5));
4355 assert(!startsWith(arr, 1));
4356 assert(startsWith(arr, 0));
4357 assert(startsWith(arr, 5, 0, 1) == 2);
4358 assert(startsWith(arr, [0]));
4359 assert(startsWith(arr, [0, 1]));
4360 assert(startsWith(arr, [0, 1], 7) == 1);
4361 assert(!startsWith(arr, [0, 1, 7]));
4362 assert(startsWith(arr, [0, 1, 7], [0, 1, 2]) == 2);
4363
4364 //Normal input range
4365 assert(!startsWith(filter!"true"(arr), 1));
4366 assert(startsWith(filter!"true"(arr), 0));
4367 assert(startsWith(filter!"true"(arr), [0]));
4368 assert(startsWith(filter!"true"(arr), [0, 1]));
4369 assert(startsWith(filter!"true"(arr), [0, 1], 7) == 1);
4370 assert(!startsWith(filter!"true"(arr), [0, 1, 7]));
4371 assert(startsWith(filter!"true"(arr), [0, 1, 7], [0, 1, 2]) == 2);
4372 assert(startsWith(arr, filter!"true"([0, 1])));
4373 assert(startsWith(arr, filter!"true"([0, 1]), 7) == 1);
4374 assert(!startsWith(arr, filter!"true"([0, 1, 7])));
4375 assert(startsWith(arr, [0, 1, 7], filter!"true"([0, 1, 2])) == 2);
4376
4377 //Non-default pred
4378 assert(startsWith!("a%10 == b%10")(arr, [10, 11]));
4379 assert(!startsWith!("a%10 == b%10")(arr, [10, 12]));
4380 }
4381}
4382
4383/* (Not yet documented.)
4384Consume all elements from $(D r) that are equal to one of the elements
4385$(D es).
4386 */
4387private void skipAll(alias pred = "a == b", R, Es...)(ref R r, Es es)
4388//if (is(typeof(binaryFun!pred(r1.front, es[0]))))
4389{
4390 loop:
4391 for (; !r.empty; r.popFront())
4392 {
4393 foreach (i, E; Es)
4394 {
4395 if (binaryFun!pred(r.front, es[i]))
4396 {
4397 continue loop;
4398 }
4399 }
4400 break;
4401 }
4402}
4403
4404@safe unittest
4405{
4406 auto s1 = "Hello world";
4407 skipAll(s1, 'H', 'e');
4408 assert(s1 == "llo world");
4409}
4410
4411/**
4412Interval option specifier for `until` (below) and others.
4413
4414If set to $(D OpenRight.yes), then the interval is open to the right
4415(last element is not included).
4416
4417Otherwise if set to $(D OpenRight.no), then the interval is closed to the right
4418(last element included).
4419 */
4420alias OpenRight = Flag!"openRight";
4421
4422/**
4423Lazily iterates $(D range) _until the element $(D e) for which
4424$(D pred(e, sentinel)) is true.
4425
4426This is similar to `takeWhile` in other languages.
4427
4428Params:
4429 pred = Predicate to determine when to stop.
4430 range = The $(REF_ALTTEXT input _range, isInputRange, std,_range,primitives)
4431 to iterate over.
4432 sentinel = The element to stop at.
4433 openRight = Determines whether the element for which the given predicate is
4434 true should be included in the resulting range ($(D No.openRight)), or
4435 not ($(D Yes.openRight)).
4436
4437Returns:
4438 An $(REF_ALTTEXT input _range, isInputRange, std,_range,primitives) that
4439 iterates over the original range's elements, but ends when the specified
4440 predicate becomes true. If the original range is a
4441 $(REF_ALTTEXT forward _range, isForwardRange, std,_range,primitives) or
4442 higher, this range will be a forward range.
4443 */
4444Until!(pred, Range, Sentinel)
4445until(alias pred = "a == b", Range, Sentinel)
4446(Range range, Sentinel sentinel, OpenRight openRight = Yes.openRight)
4447if (!is(Sentinel == OpenRight))
4448{
4449 return typeof(return)(range, sentinel, openRight);
4450}
4451
4452/// Ditto
4453Until!(pred, Range, void)
4454until(alias pred, Range)
4455(Range range, OpenRight openRight = Yes.openRight)
4456{
4457 return typeof(return)(range, openRight);
4458}
4459
4460/// ditto
4461struct Until(alias pred, Range, Sentinel)
4462if (isInputRange!Range)
4463{
4464 private Range _input;
4465 static if (!is(Sentinel == void))
4466 private Sentinel _sentinel;
4467 private OpenRight _openRight;
4468 private bool _done;
4469
4470 static if (!is(Sentinel == void))
4471 ///
4472 this(Range input, Sentinel sentinel,
4473 OpenRight openRight = Yes.openRight)
4474 {
4475 _input = input;
4476 _sentinel = sentinel;
4477 _openRight = openRight;
4478 _done = _input.empty || openRight && predSatisfied();
4479 }
4480 else
4481 ///
4482 this(Range input, OpenRight openRight = Yes.openRight)
4483 {
4484 _input = input;
4485 _openRight = openRight;
4486 _done = _input.empty || openRight && predSatisfied();
4487 }
4488
4489 ///
4490 @property bool empty()
4491 {
4492 return _done;
4493 }
4494
4495 ///
4496 @property auto ref front()
4497 {
4498 assert(!empty);
4499 return _input.front;
4500 }
4501
4502 private bool predSatisfied()
4503 {
4504 static if (is(Sentinel == void))
4505 return cast(bool) unaryFun!pred(_input.front);
4506 else
4507 return cast(bool) startsWith!pred(_input, _sentinel);
4508 }
4509
4510 ///
4511 void popFront()
4512 {
4513 assert(!empty);
4514 if (!_openRight)
4515 {
4516 _done = predSatisfied();
4517 _input.popFront();
4518 _done = _done || _input.empty;
4519 }
4520 else
4521 {
4522 _input.popFront();
4523 _done = _input.empty || predSatisfied();
4524 }
4525 }
4526
4527 static if (isForwardRange!Range)
4528 {
4529 static if (!is(Sentinel == void))
4530 ///
4531 @property Until save()
4532 {
4533 Until result = this;
4534 result._input = _input.save;
4535 result._sentinel = _sentinel;
4536 result._openRight = _openRight;
4537 result._done = _done;
4538 return result;
4539 }
4540 else
4541 ///
4542 @property Until save()
4543 {
4544 Until result = this;
4545 result._input = _input.save;
4546 result._openRight = _openRight;
4547 result._done = _done;
4548 return result;
4549 }
4550 }
4551}
4552
4553///
4554@safe unittest
4555{
4556 import std.algorithm.comparison : equal;
4557 import std.typecons : No;
4558 int[] a = [ 1, 2, 4, 7, 7, 2, 4, 7, 3, 5];
4559 assert(equal(a.until(7), [1, 2, 4]));
4560 assert(equal(a.until(7, No.openRight), [1, 2, 4, 7]));
4561}
4562
4563@safe unittest
4564{
4565 import std.algorithm.comparison : equal;
4566 int[] a = [ 1, 2, 4, 7, 7, 2, 4, 7, 3, 5];
4567
4568 static assert(isForwardRange!(typeof(a.until(7))));
4569 static assert(isForwardRange!(typeof(until!"a == 2"(a, No.openRight))));
4570
4571 assert(equal(a.until(7), [1, 2, 4]));
4572 assert(equal(a.until([7, 2]), [1, 2, 4, 7]));
4573 assert(equal(a.until(7, No.openRight), [1, 2, 4, 7]));
4574 assert(equal(until!"a == 2"(a, No.openRight), [1, 2]));
4575}
4576
4577@system unittest // bugzilla 13171
4578{
4579 import std.algorithm.comparison : equal;
4580 import std.range;
4581 auto a = [1, 2, 3, 4];
4582 assert(equal(refRange(&a).until(3, No.openRight), [1, 2, 3]));
4583 assert(a == [4]);
4584}
4585
4586@safe unittest // Issue 10460
4587{
4588 import std.algorithm.comparison : equal;
4589 auto a = [1, 2, 3, 4];
4590 foreach (ref e; a.until(3))
4591 e = 0;
4592 assert(equal(a, [0, 0, 3, 4]));
4593}
4594
4595@safe unittest // Issue 13124
4596{
4597 import std.algorithm.comparison : among, equal;
4598 auto s = "hello how\nare you";
4599 assert(equal(s.until!(c => c.among!('\n', '\r')), "hello how"));
4600}