Spec-Zone.ru › D

std.algorithm.comparison

Это подмодуль std.algorithm. Он содержит общие алгоритмы сравнения.

Справочник
Имя функции Описание
among Проверяет, является ли значение одним из набора значений, например, if (v.among(1, 2, 3)) // v is 1, 2 or 3
castSwitch (new A()).castSwitch((A a)=>1,(B b)=>2) возвращает 1.
clamp clamp(1, 3, 6) возвращает 3. clamp(4, 3, 6) возвращает 4.
cmp cmp("abc", "abcd") это -1, cmp("abc", "aba") это 1, а cmp("abc", "abc") это 0.
either Возвращает первый параметр p, который проходит тест if (p), например, either(0, 42, 43) возвращает 42.
equal Сравнивает диапазоны на равенство элементов попарно, например, equal([1, 2, 3], [1.0, 2.0, 3.0]) возвращает true.
isPermutation isPermutation([1, 2], [2, 1]) возвращает true.
isSameLength isSameLength([1, 2, 3], [4, 5, 6]) возвращает true.
levenshteinDistance levenshteinDistance("kitten", "sitting") возвращает 3, используя алгоритм расстояния Левенштейна.
levenshteinDistanceAndPath levenshteinDistanceAndPath("kitten", "sitting") возвращает tuple(3, "snnnsni"), используя алгоритм расстояния Левенштейна.
max max(3, 4, 2) возвращает 4.
min min(3, 4, 2) возвращает 2.
mismatch mismatch("oh hi", "ohayo") возвращает tuple(" hi", "ayo").
predSwitch 2.predSwitch(1, "one", 2, "two", 3, "three") возвращает "two".

Лицензия:
Лицензия Boost 1.0.
Авторы:
Андрей Александреску
Исходный код
std/algorithm/comparison.d
END_OF_DOCUMENT_MARKER
uint among(alias pred = (a, b) => a == b, Value, Values...)(Value value, Values values)
Constraints: if (Values.length != 0);

template among(values...) if (isExpressionTuple!values)

Найти value среди values, возвращая индекс первого совпавшего значения в values, или 0 если value не среди values. Предикат pred используется для сравнения значений, по умолчанию используется равенство.

Параметры:
pred Предикат, используемый для сравнения значений.
Value value Значение, которое нужно найти.
Values values Значения, с которыми нужно сравнить искомое значение.
Возвращает:
0, если значение не найдено среди значений, иначе возвращается индекс найденного значения плюс один.
См. также:
find и canFind для поиска значения в диапазоне.
Примеры:
assert(3.among(1, 42, 24, 3, 2));

if (auto pos = "bar".among("foo", "bar", "baz"))
    writeln(pos); // 2
else
    assert(false);

// 42 is larger than 24
writeln(42.among!((lhs, rhs) => lhs > rhs)(43, 24, 100)); // 2
Примеры:
В качестве альтернативы, values может быть передан во время компиляции, что позволяет выполнить более эффективный поиск, но поддерживает только сравнение на равенство:
assert(3.among!(2, 3, 4));
writeln("bar".among!("foo", "bar", "baz")); // 2
auto castSwitch(choices...)(Object switchObject);

Выполняет и возвращает один из набора обработчиков, основываясь на типе объекта switch.

Первый вариант, к которому switchObject может быть приведен к типу аргумента, который он принимает, будет вызван с switchObject приведённым к этому типу, и возвращаемое им значение будет возвращено castSwitch.

Если возвращаемый тип варианта void, вариант должен сгенерировать исключение, если все варианты void. В этом случае castSwitch вернёт void.

Исключения:
Если ни один из вариантов не соответствует, будет сгенерировано SwitchError. SwitchError также будет сгенерировано, если не все варианты void, и void-вариант был выполнен без генерации исключения.
Параметры:
choices Варианты должны состоять из функций или делегатов-обработчиков, принимающих один аргумент. Также может быть вариант, принимающий ноль аргументов. Этот вариант будет вызван, если switchObject имеет значение null.
Object switchObject Объект, с которым выполняются проверки.
Возвращает:
Значение выбранного варианта.
Примечание
castSwitch может быть использован только с объектами.
Примеры:
import std.algorithm.iteration : map;
import std.format : format;

class A
{
    int a;
    this(int a) {this.a = a;}
    @property int i() { return a; }
}
interface I { }
class B : I { }

Object[] arr = [new A(1), new B(), null];

auto results = arr.map!(castSwitch!(
                            (A a) => "A with a value of %d".format(a.a),
                            (I i) => "derived from I",
                            ()    => "null reference",
                        ))();

// A is handled directly:
writeln(results[0]); // "A with a value of 1"
// B has no handler - it is handled by the handler of I:
writeln(results[1]); // "derived from I"
// null is handled by the null handler:
writeln(results[2]); // "null reference"
Примеры:
Использование с void-обработчиками:
import std.exception : assertThrown;

class A { }
class B { }
// Void handlers are allowed if they throw:
assertThrown!Exception(
    new B().castSwitch!(
        (A a) => 1,
        (B d)    { throw new Exception("B is not allowed!"); }
    )()
);

// Void handlers are also allowed if all the handlers are void:
new A().castSwitch!(
    (A a) { },
    (B b) { assert(false); },
)();
auto clamp(T1, T2, T3)(T1 val, T2 lower, T3 upper)
Constraints: if (is(typeof(max(min(val, upper), lower))));

Ограничивает значение заданными пределами.

Эта функция эквивалентна max(lower, min(upper, val)).

Параметры:
T1 val Значение, которое нужно ограничить.
T2 lower Нижняя граница ограничения.
T3 upper Верхняя граница ограничения.
Возвращает:
Возвращает val, если оно находится между lower и upper. В противном случае возвращает ближайшее из двух значений.
Примеры:
writeln(clamp(2, 1, 3)); // 2
writeln(clamp(0, 1, 3)); // 1
writeln(clamp(4, 1, 3)); // 3

writeln(clamp(1, 1, 1)); // 1

writeln(clamp(5, -1, 2u)); // 2
auto cmp(R1, R2)(R1 r1, R2 r2)
Constraints: if (isInputRange!R1 && isInputRange!R2);

int cmp(alias pred, R1, R2)(R1 r1, R2 r2)
Constraints: if (isInputRange!R1 && isInputRange!R2);

Выполняет лексикографическое сравнение двух входных диапазонов. Итерируя r1 и r2 синхронно, cmp сравнивает каждый элемент e1 из r1 с соответствующим элементом e2 в r2. Если один из диапазонов закончился, cmp возвращает отрицательное значение, если r1 имеет меньше элементов, чем r2, положительное значение, если r1 имеет больше элементов, чем r2, и 0 если диапазоны имеют одинаковое количество элементов.

Если диапазоны являются строками, cmp выполняет соответствующее декодирование UTF и сравнивает диапазоны по одному кодовому элементу за раз.

Можно указать пользовательский предикат, в этом случае cmp выполняет лексикографическое сравнение с помощью pred. В противном случае элементы сравниваются с помощью opCmp.

Параметры:
pred Предикат, используемый для сравнения. Без указанного предиката используется порядок, подразумеваемый opCmp
R1 r1 Первый диапазон.
R2 r2 Второй диапазон.
Возвращает:
0 если диапазоны равны. Отрицательное значение, если r1 является префиксом r2 или первый отличающийся элемент r1 меньше соответствующего элемента r2 в соответствии с pred. Положительное значение, если r2 является префиксом r1 или первый отличающийся элемент r2 меньше соответствующего элемента r1 в соответствии с pred.
Примечание
В более ранней версии документации неправильно утверждалось, что -1 является единственным возвращаемым отрицательным значением, а 1 - единственным положительным. Верно ли это, зависит от типов, которые сравниваются.
Примеры:
int result;

result = cmp("abc", "abc");
writeln(result); // 0
result = cmp("", "");
writeln(result); // 0
result = cmp("abc", "abcd");
assert(result < 0);
result = cmp("abcd", "abc");
assert(result > 0);
result = cmp("abc"d, "abd");
assert(result < 0);
result = cmp("bbc", "abc"w);
assert(result > 0);
result = cmp("aaa", "aaaa"d);
assert(result < 0);
result = cmp("aaaa", "aaa"d);
assert(result > 0);
result = cmp("aaa", "aaa"d);
writeln(result); // 0
result = cmp("aaa"d, "aaa"d);
writeln(result); // 0
result = cmp(cast(int[])[], cast(int[])[]);
writeln(result); // 0
result = cmp([1, 2, 3], [1, 2, 3]);
writeln(result); // 0
result = cmp([1, 3, 2], [1, 2, 3]);
assert(result > 0);
result = cmp([1, 2, 3], [1L, 2, 3, 4]);
assert(result < 0);
result = cmp([1L, 2, 3], [1, 2]);
assert(result > 0);
Примеры:
Пример предиката, который сравнивает отдельные элементы в обратном лексикографическом порядке
int result;

result = cmp!"a > b"("abc", "abc");
writeln(result); // 0
result = cmp!"a > b"("", "");
writeln(result); // 0
result = cmp!"a > b"("abc", "abcd");
assert(result < 0);
result = cmp!"a > b"("abcd", "abc");
assert(result > 0);
result = cmp!"a > b"("abc"d, "abd");
assert(result > 0);
result = cmp!"a > b"("bbc", "abc"w);
assert(result < 0);
result = cmp!"a > b"("aaa", "aaaa"d);
assert(result < 0);
result = cmp!"a > b"("aaaa", "aaa"d);
assert(result > 0);
result = cmp!"a > b"("aaa", "aaa"d);
writeln(result); // 0
result = cmp("aaa"d, "aaa"d);
writeln(result); // 0
result = cmp!"a > b"(cast(int[])[], cast(int[])[]);
writeln(result); // 0
result = cmp!"a > b"([1, 2, 3], [1, 2, 3]);
writeln(result); // 0
result = cmp!"a > b"([1, 3, 2], [1, 2, 3]);
assert(result < 0);
result = cmp!"a > b"([1, 2, 3], [1L, 2, 3, 4]);
assert(result < 0);
result = cmp!"a > b"([1L, 2, 3], [1, 2]);
assert(result > 0);
template equal(alias pred = "a == b")

Сравнивает два диапазона на равенство, как определено предикатом pred (по умолчанию ==).

Примеры:
import std.algorithm.comparison : equal;
import std.math : approxEqual;

int[4] a = [ 1, 2, 4, 3 ];
assert(!equal(a[], a[1..$]));
assert(equal(a[], a[]));
assert(equal!((a, b) => a == b)(a[], a[]));

// different types
double[4] b = [ 1.0, 2, 4, 3];
assert(!equal(a[], b[1..$]));
assert(equal(a[], b[]));

// predicated: ensure that two vectors are approximately equal
double[4] c = [ 1.005, 2, 4, 3];
assert(equal!approxEqual(b[], c[]));
Примеры:
Подсказка: equal может использоваться в качестве предиката для других функций. Это может быть очень полезно, когда тип элемента диапазона сам по себе является диапазоном. В частности, equal может быть собственным предикатом, что позволяет сравнивать диапазоны диапазонов (диапазонов...диапазонов).
import std.algorithm.comparison : equal;
import std.range : iota, chunks;
assert(equal!(equal!equal)(
    [[[0, 1], [2, 3]], [[4, 5], [6, 7]]],
    iota(0, 8).chunks(2).chunks(2)
));
bool equal(Range1, Range2)(Range1 r1, Range2 r2)
Constraints: if (isInputRange!Range1 && isInputRange!Range2 && !(isInfinite!Range1 && isInfinite!Range2) && is(typeof(binaryFun!pred(r1.front, r2.front))));

Сравнивает два диапазона на равенство. Диапазоны могут иметь разные типы элементов, если pred(r1.front, r2.front) вычисляется как bool. Выполняет Ο(min(r1.length, r2.length)) вычислений pred.

По крайней мере один из диапазонов должен быть конечным. Если один из диапазонов бесконечен, результат (статически известен как) false.

Если два диапазона представляют разные типы кодовых единиц UTF (char, wchar, или dchar), то массивы сравниваются с использованием декодирования UTF, чтобы избежать случайного повышения целых чисел.

Параметры:
Range1 r1 Первый диапазон для сравнения.
Range2 r2 Второй диапазон для сравнения.
Возвращает:
true тогда и только тогда, когда два диапазона равны по элементам, согласно бинарному предикату pred.
enum EditOp: char;

Кодирует операции редактирования, необходимые для преобразования одной последовательности в другую. Даны последовательности s (источник) и t (цель), последовательность EditOp кодирует шаги, которые необходимо выполнить для преобразования s в t. Например, если s = "cat" и "cars", минимальная последовательность, преобразующая s в t : пропустить две буквы, заменить 't' на 'r' и вставить 's'. Работа с операциями редактирования полезна в приложениях, таких как spell-checkers (для поиска ближайшего слова к заданному ошибочному), приближённый поиск, программы типа diff, которые вычисляют разницу между файлами, эффективное кодирование исправлений, анализ последовательностей ДНК и обнаружение плагиата.

Примеры:
with(EditOp)
{
    // [none, none, none, insert, insert, insert]
    writeln(levenshteinDistanceAndPath("foo", "foobar")[1]);
    // [substitute, none, substitute, none, none, remove]
    writeln(levenshteinDistanceAndPath("banana", "fazan")[1]);
}
none

Текущие элементы равны; редактирование не требуется.

substitute

Заменить текущий элемент в целевой последовательности текущим элементом в исходной последовательности.

insert

Вставить текущий элемент из исходной последовательности в целевую.

remove

Удалить текущий элемент из целевой последовательности.

size_t levenshteinDistance(alias equals = (a, b) => a == b, Range1, Range2)(Range1 s, Range2 t)
Constraints: if (isForwardRange!Range1 && isForwardRange!Range2);

size_t levenshteinDistance(alias equals = (a, b) => a == b, Range1, Range2)(auto ref Range1 s, auto ref Range2 t)
Constraints: if (isConvertibleToString!Range1 || isConvertibleToString!Range2);

Возвращает расстояние Левенштейна между s и t. Расстояние Левенштейна вычисляет минимальное количество операций редактирования, необходимых для преобразования s в t. Выполняет Ο(s.length * t.length) вычислений equals и занимает Ο(min(s.length, t.length)) памяти.

Параметры:
equals Бинарный предикат для сравнения элементов двух диапазонов.
Range1 s Исходный диапазон.
Range2 t Целевой диапазон преобразования.
Возвращает:
Минимальное количество правок для преобразования s в t. Не выделяет память GC.
Примеры:
import std.algorithm.iteration : filter;
import std.uni : toUpper;

writeln(levenshteinDistance("cat", "rat")); // 1
writeln(levenshteinDistance("parks", "spark")); // 2
writeln(levenshteinDistance("abcde", "abcde")); // 0
writeln(levenshteinDistance("abcde", "abCde")); // 1
writeln(levenshteinDistance("kitten", "sitting")); // 3
assert(levenshteinDistance!((a, b) => toUpper(a) == toUpper(b))
    ("parks", "SPARK") == 2);
writeln(levenshteinDistance("parks".filter!"true", "spark".filter!"true")); // 2
writeln(levenshteinDistance("ID", "I♥D")); // 1
Tuple!(size_t, EditOp[]) levenshteinDistanceAndPath(alias equals = (a, b) => a == b, Range1, Range2)(Range1 s, Range2 t)
Constraints: if (isForwardRange!Range1 && isForwardRange!Range2);

Tuple!(size_t, EditOp[]) levenshteinDistanceAndPath(alias equals = (a, b) => a == b, Range1, Range2)(auto ref Range1 s, auto ref Range2 t)
Constraints: if (isConvertibleToString!Range1 || isConvertibleToString!Range2);

Возвращает расстояние Левенштейна и путь редактирования между s и t.

Параметры:
equals Бинарный предикат для сравнения элементов двух диапазонов.
Range1 s Исходный диапазон.
Range2 t Целевой диапазон преобразования.
Возвращает:
Кортеж, где первый элемент — минимальное количество правок для преобразования s в t, а второй — последовательность правок для этого преобразования. Выделяет память GC для возвращаемого массива EditOp[].
Примеры:
string a = "Saturday", b = "Sundays";
auto p = levenshteinDistanceAndPath(a, b);
writeln(p[0]); // 4
assert(equal(p[1], "nrrnsnnni"));
auto max(T...)(T args)
Constraints: if (T.length >= 2 && !is(CommonType!T == void));

Проходит по переданным аргументам и возвращает максимальное значение.

Параметры:
T args Значения, для которых нужно выбрать максимальное. Должно быть передано как минимум два аргумента, и они должны быть сравнимы с >.
Возвращает:
Максимальное из переданных значений. Тип возвращаемого значения — тип среди переданных аргументов, способный хранить наибольшее значение. Если хотя бы один из аргументов — NaN, результат — неопределенное значение. См. std.algorithm.searching.maxElement для примеров работы с NaN.
См. также:
std.algorithm.searching.maxElement
Примеры:
int a = 5;
short b = 6;
double c = 2;
auto d = max(a, b);
assert(is(typeof(d) == int));
writeln(d); // 6
auto e = min(a, b, c);
assert(is(typeof(e) == double));
writeln(e); // 2
auto min(T...)(T args)
Constraints: if (T.length >= 2 && !is(CommonType!T == void));

Проходит по переданным аргументам и возвращает минимальное значение.

Параметры:
T args Значения, для которых нужно выбрать минимальное. Должно быть передано как минимум два аргумента, и они должны быть сравнимы с <.
Возвращает:
Минимальное из переданных значений. Тип возвращаемого значения — тип среди переданных аргументов, способный хранить наименьшее значение. Если хотя бы один из аргументов — NaN, результат — неопределенное значение. См. std.algorithm.searching.minElement для примеров работы с NaN.
См. также:
std.algorithm.searching.minElement
Примеры:
int a = 5;
short b = 6;
double c = 2;
auto d = min(a, b);
static assert(is(typeof(d) == int));
writeln(d); // 5
auto e = min(a, b, c);
static assert(is(typeof(e) == double));
writeln(e); // 2
ulong f = 0xffff_ffff_ffff;
const uint g = min(f, 0xffff_0000);
writeln(g); // 0xffff_0000
dchar h = 100;
uint i = 101;
static assert(is(typeof(min(h, i)) == dchar));
static assert(is(typeof(min(i, h)) == uint));
writeln(min(h, i)); // 100
Примеры:
При аргументах смешанной знаковости, тип возвращаемого значения — тот, что способен хранить наименьшие значения.
int a = -10;
uint f = 10;
static assert(is(typeof(min(a, f)) == int));
writeln(min(a, f)); // -10
Примеры:
Поддерживаются пользовательские типы, поддерживающие сравнение с <.
import std.datetime;
writeln(min(Date(2012, 12, 21), Date(1982, 1, 4))); // Date(1982, 1, 4)
writeln(min(Date(1982, 1, 4), Date(2012, 12, 21))); // Date(1982, 1, 4)
writeln(min(Date(1982, 1, 4), Date.min)); // Date.min
writeln(min(Date.min, Date(1982, 1, 4))); // Date.min
writeln(min(Date(1982, 1, 4), Date.max)); // Date(1982, 1, 4)
writeln(min(Date.max, Date(1982, 1, 4))); // Date(1982, 1, 4)
writeln(min(Date.min, Date.max)); // Date.min
writeln(min(Date.max, Date.min)); // Date.min
Tuple!(Range1, Range2) mismatch(alias pred = "a == b", Range1, Range2)(Range1 r1, Range2 r2)
Constraints: if (isInputRange!Range1 && isInputRange!Range2);

Последовательно сравнивает элементы в r1 и r2 пошагово и останавливается на первой несовпадении (согласно pred, по умолчанию равенству). Возвращает кортеж с уменьшенными диапазонами, начинающимися с двух несовпадающих значений. Выполняет Ο(min(r1.length, r2.length)) вычислений pred.

Примеры:
int[6] x = [ 1,   5, 2, 7,   4, 3 ];
double[6] y = [ 1.0, 5, 2, 7.3, 4, 8 ];
auto m = mismatch(x[], y[]);
writeln(m[0]); // x[3 .. &dollar;]
writeln(m[1]); // y[3 .. &dollar;]
auto predSwitch(alias pred = "a == b", T, R...)(T switchExpression, lazy R choices);

Возвращает одно из набора выражений на основе значения выражения переключения.

choices должен состоять из пар выражений проверки и выражений возврата. Каждое выражение проверки сравнивается с switchExpression с использованием pred (switchExpression — первый аргумент), и если это даёт true — возвращается выражение возврата.

И выражения проверки, и выражения возврата вычисляются лениво.

Параметры:
T switchExpression Первый аргумент для предиката.
R choices Пары выражений проверки и выражений возврата. Выражения проверки будут вторым аргументом для предиката, и выражение возврата будет возвращено, если предикат даёт true с switchExpression и выражением проверки в качестве аргументов. Может также иметь выражение возврата по умолчанию, которое должно быть последним выражением без выражения проверки перед ним. Выражение возврата может быть только типа void, если оно всегда вызывает исключение.
Возвращает:
Выражение возврата, связанное с первым выражением проверки, которое заставило предикат вернуть true, или выражение возврата по умолчанию, если ни одно выражение проверки не совпало.
Исключения:
Если нет выражения возврата по умолчанию и предикат не возвращает true ни с одним выражением проверки — выбрасывается SwitchError. SwitchError также будет вызвано, если выражение возврата типа void было выполнено без возбуждения исключения.
Примеры:
string res = 2.predSwitch!"a < b"(
    1, "less than 1",
    5, "less than 5",
    10, "less than 10",
    "greater or equal to 10");

writeln(res); // "less than 5"

//The arguments are lazy, which allows us to use predSwitch to create
//recursive functions:
int factorial(int n)
{
    return n.predSwitch!"a <= b"(
        -1, {throw new Exception("Can not calculate n! for n < 0");}(),
        0, 1, // 0! = 1
        n * factorial(n - 1) // n! = n * (n - 1)! for n >= 0
        );
}
writeln(factorial(3)); // 6

//Void return expressions are allowed if they always throw:
import std.exception : assertThrown;
assertThrown!Exception(factorial(-9));
bool isSameLength(Range1, Range2)(Range1 r1, Range2 r2)
Constraints: if (isInputRange!Range1 && isInputRange!Range2);

Проверяет, имеют ли два диапазона одинаковое количество элементов. Эта функция оптимизирована для использования члена length любого диапазона, если он существует.

Если у обоих диапазонов есть член length, эта функция имеет сложность Ο(1). В противном случае сложность Ο(min(r1.length, r2.length)).

Бесконечные диапазоны считаются имеющими одинаковую длину. Бесконечный диапазон никогда не имеет одинаковую длину с конечным диапазоном.

Параметры:
Range1 r1 конечный входной диапазон
Range2 r2 конечный входной диапазон
Возвращает:
true если оба диапазона имеют одинаковую длину, false в противном случае.
Примеры:
assert(isSameLength([1, 2, 3], [4, 5, 6]));
assert(isSameLength([0.3, 90.4, 23.7, 119.2], [42.6, 23.6, 95.5, 6.3]));
assert(isSameLength("abc", "xyz"));

int[] a;
int[] b;
assert(isSameLength(a, b));

assert(!isSameLength([1, 2, 3], [4, 5]));
assert(!isSameLength([0.3, 90.4, 23.7], [42.6, 23.6, 95.5, 6.3]));
assert(!isSameLength("abcd", "xyz"));
bool isPermutation(Flag!"allocateGC" allocateGC, Range1, Range2)(Range1 r1, Range2 r2)
Constraints: if (allocateGC == Yes.allocateGC && isForwardRange!Range1 && isForwardRange!Range2 && !isInfinite!Range1 && !isInfinite!Range2);

bool isPermutation(alias pred = "a == b", Range1, Range2)(Range1 r1, Range2 r2)
Constraints: if (is(typeof(binaryFun!pred)) && isForwardRange!Range1 && isForwardRange!Range2 && !isInfinite!Range1 && !isInfinite!Range2);

Проверяет, являются ли оба диапазона перестановкой друг друга.

Эта функция может выделять память, если флаг Yes.allocateGC передан. Это даёт преимущество в сложности по сравнению с вариантом Yes.allocateGC. Однако этот вариант доступен только для диапазонов, равенство которых может быть определено с помощью метода toHash каждого элемента. Если требуется настраиваемое равенство, то может быть передан шаблонный параметр pred, и функция автоматически переключится на невыделяющий алгоритм. См. std.functional.binaryFun для получения более подробной информации о том, как определить pred.

Вариант невыделяющего диапазона с forward: Ο(n^2) Вариант невыделяющего диапазона с forward и настраиваемым pred: Ο(n^2) Вариант выделяющего диапазона с forward: амортизированное Ο(r1.length) + Ο(r2.length)

Параметры:
pred необязательный параметр для изменения определения равенства
allocateGC Yes.allocateGC/No.allocateGC
Range1 r1 Конечный forward диапазон
Range2 r2 Конечный forward диапазон
Возвращает:
true если все элементы в r1 появляются одинаковое количество раз в r2. В противном случае возвращает false.
Примеры:
import std.typecons : Yes;

assert(isPermutation([1, 2, 3], [3, 2, 1]));
assert(isPermutation([1.1, 2.3, 3.5], [2.3, 3.5, 1.1]));
assert(isPermutation("abc", "bca"));

assert(!isPermutation([1, 2], [3, 4]));
assert(!isPermutation([1, 1, 2, 3], [1, 2, 2, 3]));
assert(!isPermutation([1, 1], [1, 1, 1]));

// Faster, but allocates GC handled memory
assert(isPermutation!(Yes.allocateGC)([1.1, 2.3, 3.5], [2.3, 3.5, 1.1]));
assert(!isPermutation!(Yes.allocateGC)([1, 2], [3, 4]));
CommonType!(T, Ts) either(alias pred = (a) => a, T, Ts...)(T first, lazy Ts alternatives)
Constraints: if (alternatives.length >= 1 && !is(CommonType!(T, Ts) == void) && allSatisfy!(ifTestable, T, Ts));

Получить первый аргумент a , который проходит if (unaryFun!pred(a)) тест. Если ни один аргумент не проходит тест, вернуть последний аргумент.

Аналогично поведению оператора or в динамических языках, таких как Lisp's (or ...) и Python's a or b or ..., за исключением того, что при отсутствии совпадения возвращается последний аргумент.

Упрощает логику, например, в правилах разбора, где пытаются сопоставить набор альтернативных проверяющих средств. Первый, который совпадёт, возвращает результат его сопоставления, как правило, в виде абстрактного синтаксического дерева (AST).

Ошибки:
Ленивые параметры в настоящее время слишком ограничительно выводятся DMD как всегда выбрасывающие исключение, даже если это не требуется. Это делает невозможным в настоящее время пометить either как nothrow. См. вопрос в Bugzilla 12647.
Возвращаемое значение:
Первый аргумент, который проходит тест pred.
Примеры:
const a = 1;
const b = 2;
auto ab = either(a, b);
static assert(is(typeof(ab) == const(int)));
writeln(ab); // a

auto c = 2;
const d = 3;
auto cd = either!(a => a == 3)(c, d); // use predicate
static assert(is(typeof(cd) == int));
writeln(cd); // d

auto e = 0;
const f = 2;
auto ef = either(e, f);
static assert(is(typeof(ef) == int));
writeln(ef); // f
Примеры:
immutable p = 1;
immutable q = 2;
auto pq = either(p, q);
static assert(is(typeof(pq) == immutable(int)));
writeln(pq); // p

writeln(either(3, 4)); // 3
writeln(either(0, 4)); // 4
writeln(either(0, 0)); // 0
writeln(either("", "a")); // ""
Примеры:
string r = null;
writeln(either(r, "a")); // "a"
writeln(either("a", "")); // "a"

immutable s = [1, 2];
writeln(either(s, s)); // s

writeln(either([0, 1], [1, 2])); // [0, 1]
writeln(either([0, 1], [1])); // [0, 1]
writeln(either("a", "b")); // "a"

static assert(!__traits(compiles, either(1, "a")));
static assert(!__traits(compiles, either(1.0, "a")));
static assert(!__traits(compiles, either('a', "a")));

© 1999–2021 The D Language Foundation
Licensed under the Boost License 1.0.
https://dlang.org/phobos/std_algorithm_comparison.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API