Переместиться к: AllocateGC · among · castSwitch · clamp · cmp · EditOp · either · equal · isPermutation · isSameLength · levenshteinDistance · levenshteinDistanceAndPath · max · min · mismatch · predSwitch
Имя функции | Описание |
---|---|
among | Проверяет, присутствует ли значение среди набора значений, например if (v.among(1, 2, 3)) // v - это 1, 2 или 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". |
Исходный код: std/algorithm/comparison.d
among
(alias pred = (a, b) => a == b, Value, Values...)(Value value
, Values values
)among
(values...) if (isExpressionTuple!values)value
среди values
, возвращая начинающийся с единицы индекс первого совпадающего значения в values
, или 0, если value
отсутсвует среди values
. Предикат pred используется для сравнения значений и использует равенство по умолчанию.
pred | Предикат, используемый для сравнения значений. |
Value value |
Искомое значение. |
Values values |
Значения, которые сравниваются с value . |
value
не было обнаружено среди values
, в противном случае возвращается индекс обнаруженного значения плюс один.
assert(3.among(1, 42, 24, 3, 2)); if (auto pos = "bar".among("foo", "bar", "baz")) assert(pos == 2); else assert(false); // 42 больше, чем 24 assert(42.among!((lhs, rhs) => lhs > rhs)(43, 24, 100) == 2);
values
могут быть переданы во время компиляции, что позволяет проводить более эффективный поиск, но в этом случае поддерживается сопоставление только на равенство:
assert(3.among!(2, 3, 4)); assert("bar".among!("foo", "bar", "baz") == 2);
castSwitch
(choices...)(Object switchObject
);
switchObject
может быть приведён по типу аргумента, будет вызван с switchObject
, приведённым к этому типу, и возвращённое значение будет возвращено из castSwitch
.
Если выбранный возвращаемый тип – это void, вариант должен бросить исключение, если все варианты не являются void. В этом случае, castSwitch
сам возвращает void.
choices | Варианты 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 обрабатывается непосредственно: assert(results[0] == "A with a value of 1"); // B не имеет обработчика – применяется обработчик I: assert(results[1] == "derived from I"); // для null применяется null-обработчик: assert(results[2] == "null reference");
import std.exception : assertThrown; class A { } class B { } // Void-обработчики допустимы, если они бросают исключение: assertThrown!Exception( new B().castSwitch!( (A a) => 1, (B d) { throw new Exception("B is not allowed!"); } )() ); // Void-обработчики также допустимы, если все обработчики являются void: new A().castSwitch!( (A a) { assert(true); }, (B b) { assert(false); }, )();
clamp
(T1, T2, T3)(T1 val
, T2 lower
, T3 upper
);
lower
, min(upper
,val
)).
T1 val |
Значение для зажимания. |
T2 lower |
Нижний предел. |
T3 upper |
Верхний предел. |
val
, если оно между lower
и upper
.
В противном случае возвращает ближайший из двух.assert(clamp(2, 1, 3) == 2); assert(clamp(0, 1, 3) == 1); assert(clamp(4, 1, 3) == 3); assert(clamp(1, 1, 1) == 1); assert(clamp(5, -1, 2u) == 2);
cmp
(alias pred = "a < b", R1, R2)(R1 r1
, R2 r2
)cmp
(alias pred = "a < b", R1, R2)(R1 r1
, R2 r2
)r1
и r2
шаг-за-шагом, cmp
сравнивает каждый элемент e1 в диапазоне r1
с соответствующим элементом e2 в r2
. Если один из диапазонов завершается, cmp
возвращает отрицательную величину, если r1
имеет меньше элементов, чем r2
, положительную величину, если r1
имеет больше элементов, чем r2
, и 0 если диапазоны имеют одинаковое количество элементов.
cmp
выполняет обстоятельное UTF-декодирование и сравнивает диапазоны по одной кодовой точке (code point) за один раз.
pred | Предикат, используемый для сравнения. |
R1 r1 |
Первый диапазон. |
R2 r2 |
Второй диапазон. |
r1
меньше, чем соответствующий элемент r2
согласно предикату pred. 1, если первый отличающийся элемент r2
меньше, чем соответствующий элемент r1
согласно предикату pred.int result; result = cmp("abc", "abc"); assert(result == 0); result = cmp("", ""); assert(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); assert(result == 0); result = cmp(cast(int[])[], cast(int[])[]); assert(result == 0); result = cmp([1, 2, 3], [1, 2, 3]); assert(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);
import std.math : approxEqual; import std.algorithm.comparison : equal; int[] a = [ 1, 2, 4, 3 ]; assert(!equal(a, a[1..$])); assert(equal(a, a)); assert(equal!((a, b) => a == b)(a, a)); // различные типы double[] b = [ 1.0, 2, 4, 3]; assert(!equal(a, b[1..$])); assert(equal(a, b)); // с предикатом: убедиться, что два вектора приблизительно равны double[] c = [ 1.005, 2, 4, 3]; assert(equal!approxEqual(b, c));
equal
сама может использоваться, как предикат в других функциях. Это может быть очень полезным, когда тип элементов диапазона – сам является диапазоном. В частности, equal
может быть собственным предикатом, допускающим сравнение диапазона диапазонов (диапазонов...) .
import std.range : iota, chunks; import std.algorithm.comparison : equal; assert(equal!(equal!equal)( [[[0, 1], [2, 3]], [[4, 5], [6, 7]]], iota(0, 8).chunks(2).chunks(2) ));
equal
(Range1, Range2)(Range1 r1
, Range2 r2
)r1
.front, r2
.front))));
r1
и b в r2
.
Выполняет Ο(min(r1
.length, r2
.length)) вычислений pred.
Range1 r1 |
Первый диапазон для сравнения. |
Range2 r2 |
Второй диапазон для сравнения. |
true
тогда и только тогда, когда два диапазона равны элемент-в-элемент, в соответсвии с предикатом pred.
EditOp
кодирует шаги, которые нужно педпринять, чтобы преобразовать s в t. Например, если s = "cat" и "cars", минимальная последовательность, которая превращает s в t:
пропустить два символа, заменить 't на 'r', и вставить 's'. Работа с операциями редактирования полезна в таких приложениях, как например, программах контроля правописания (чтобы находить ближайшее к данному слову, написанному с орфографическими ошибками), приближенные поиски, diff-программы, которые вычисляют различие между файлами, эффективно кодируя патчи, анализа последовательности ДНК, и обнаружения плагиата.none
substitute
insert
remove
levenshteinDistance
(alias equals = (a, b) => a == b, Range1, Range2)(Range1 s
, Range2 t
)levenshteinDistance
(alias equals = (a, b) => a == b, Range1, Range2)(auto ref Range1 s
, auto ref Range2 t
)s
и t
. Расстояние Левенштейна вычисляет минимальное количество действий редактирования, необходимых для преобразования s
в t
. Выполняется за Ο(s
.length * t
.length) операций сравнения и занимает область в памяти размером Ο(s
.length * t
.length).
equals | Двухаргументный предикат, который сравнивает элементы двух диапазонов. |
Range1 s |
Исходный диапазон. |
Range2 t |
Цель преобразования. |
s
в t
.
Не распределяет память, управляемую сборщиком мусора.import std.algorithm.iteration : filter; import std.uni : toUpper; assert(levenshteinDistance("cat", "rat") == 1); assert(levenshteinDistance("parks", "spark") == 2); assert(levenshteinDistance("abcde", "abcde") == 0); assert(levenshteinDistance("abcde", "abCde") == 1); assert(levenshteinDistance("kitten", "sitting") == 3); assert(levenshteinDistance!((a, b) => toUpper(a) == toUpper(b)) ("parks", "SPARK") == 2); assert(levenshteinDistance("parks".filter!"true", "spark".filter!"true") == 2); assert(levenshteinDistance("ID", "I♥D") == 1);
levenshteinDistanceAndPath
(alias equals = (a, b) => a == b, Range1, Range2)(Range1 s
, Range2 t
)levenshteinDistanceAndPath
(alias equals = (a, b) => a == b, Range1, Range2)(auto ref Range1 s
, auto ref Range2 t
)s
и
t
.
equals | Двухаргументный предикат, который сравнивает элементы двух диапазонов. |
Range1 s |
Исходный диапазон. |
Range2 t |
Цель преобразования. |
s
в t
, а второй – последовательность редактирования, выполняющая это преобразование.
Распределяет память, управляемую сборщиком мусора, для возвращаемого массива EditOp[].string a = "Saturday", b = "Sundays"; auto p = levenshteinDistanceAndPath(a, b); assert(p[0] == 4); assert(equal(p[1], "nrrnsnnni"));
max
(T...)(T args
)T args |
Значения, из которых должен выбираться максимум. Должны быть переданы по крайней мере два аргумента. |
int a = 5; short b = 6; double c = 2; auto d = max(a, b); assert(is(typeof(d) == int)); assert(d == 6); auto e = min(a, b, c); assert(is(typeof(e) == double)); assert(e == 2);
min
(T...)(T args
)T args |
Значения, из которых должен выбираться максимум. Должны быть переданы по крайней мере два аргумента, и они должны быть сравнимы с помощью <. |
int a = 5; short b = 6; double c = 2; auto d = min(a, b); static assert(is(typeof(d) == int)); assert(d == 5); auto e = min(a, b, c); static assert(is(typeof(e) == double)); assert(e == 2); // С аргументами со смешанной знаковостью, типом возвращаемого значения является тот, // который может хранить самые меньшие значения. a = -10; uint f = 10; static assert(is(typeof(min(a, f)) == int)); assert(min(a, f) == -10); // Определенные пользователем типы, которые поддерживают сравнения с помощью <, поддерживаются. import std.datetime; assert(min(Date(2012, 12, 21), Date(1982, 1, 4)) == Date(1982, 1, 4)); assert(min(Date(1982, 1, 4), Date(2012, 12, 21)) == Date(1982, 1, 4)); assert(min(Date(1982, 1, 4), Date.min) == Date.min); assert(min(Date.min, Date(1982, 1, 4)) == Date.min); assert(min(Date(1982, 1, 4), Date.max) == Date(1982, 1, 4)); assert(min(Date.max, Date(1982, 1, 4)) == Date(1982, 1, 4)); assert(min(Date.min, Date.max) == Date.min); assert(min(Date.max, Date.min) == Date.min);
mismatch
(alias pred = "a == b", Range1, Range2)(Range1 r1
, Range2 r2
)r1
и r2
шаг-за-шагом, и останавливается при первом несовпадении (в соответсвии с pred, по умолчанию равенство). Возвращает кортеж с сокращёнными диапазонами, которые начинаются с двух несовпадающих величин. Выполняет Ο(min(r1
.length, r2
.length))
вычислений pred.
int[] x = [ 1, 5, 2, 7, 4, 3 ]; double[] y = [ 1.0, 5, 2, 7.3, 4, 8 ]; auto m = mismatch(x, y); assert(m[0] == x[3 .. $]); assert(m[1] == y[3 .. $]);
predSwitch
(alias pred = "a == b", T, R...)(T switchExpression
, lazy R choices
);
switchExpression
.
choices
должны быть сформированы парами из тестирующих выражений и возвращаемых выражений. Каждое тестирующее выражение сравнивается со switchExpression
, используя
pred (switchExpression
– это первый аргумент), и если получится true
– возвратится возвращаемое выражение.
Как тестирующие, так и возвращаемые выражения вычисляются лениво.
T switchExpression |
Первый аргумент для предиката. |
R choices |
Пары из тестирующих выражений и возвращаемых выражений. Тестирующие выражения будут вторым аргументом для предиката, а возвращаемое выражение будет возвращено, если результатом предиката со switchExpression и тестирующим выражением в качестве аргументов будет истина. Может также иметь возвращаемое выражение по-умолчанию, которое должно быть последним выражением без тестирующего выражения перед ним. Возвращаемое выражение может быть типа void, только если оно всегда бросает исключение. |
true
, или возвращаемое выражение по-умолчанию, если ни одно из тестирующих выражений не сработало.
string res = 2.predSwitch!"a < b"( 1, "less than 1", 5, "less than 5", 10, "less than 10", "greater or equal to 10"); assert(res == "less than 5"); //Аргументы ленивые, что позволяет нам использовать predSwitch для создания //рекурсивных функций: 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 ); } assert(factorial(3) == 6); //Возвращающие void выражения допустимы, если они всегда бросают исключение: import std.exception : assertThrown; assertThrown!Exception(factorial(-9));
isSameLength
(Range1, Range2)(Range1 r1
, Range2 r2
)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"));
AllocateGC
= std.typecons.Flag!"allocateGC".Flag;
isPermutation
(AllocateGC allocate_gc, Range1, Range2)(Range1 r1
, Range2 r2
)isPermutation
(alias pred = "a == b", Range1, Range2)(Range1 r1
, Range2 r2
)r1
.length) + Ο(r2
.length)
pred | дополнительный параметр, изменяющий определение равенства |
allocate_gc | Yes.allocateGC/No.allocateGC |
Range1 r1 |
Конечный лидирующий диапазон |
Range2 r2 |
Конечный лидирующий диапазон |
true
, если все элементы из r1
появляются то же самое количество раз в r2
.
В противном случае, возвращает false
.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])); // Быстрее, но распределяет память, управляемую сборщиком мусора assert(isPermutation!(Yes.allocateGC)([1.1, 2.3, 3.5], [2.3, 3.5, 1.1])); assert(!isPermutation!(Yes.allocateGC)([1, 2], [3, 4]));
either
(alias pred = (a) => a, T, Ts...)(T first
, lazy Ts alternatives
)alternatives
.length >= 1 && !is(CommonType!(T, Ts) == void) && allSatisfy!(ifTestable, T, Ts));
either
как nothrow. Смотрите в Bugzilla issue 12647.
const a = 1; const b = 2; auto ab = either(a, b); static assert(is(typeof(ab) == const(int))); assert(ab == a); auto c = 2; const d = 3; auto cd = either!(a => a == 3)(c, d); // используется предикат static assert(is(typeof(cd) == int)); assert(cd == d); auto e = 0; const f = 2; auto ef = either(e, f); static assert(is(typeof(ef) == int)); assert(ef == f); immutable p = 1; immutable q = 2; auto pq = either(p, q); static assert(is(typeof(pq) == immutable(int))); assert(pq == p); assert(either(3, 4) == 3); assert(either(0, 4) == 4); assert(either(0, 0) == 0); assert(either("", "a") == ""); string r = null; assert(either(r, "a") == "a"); assert(either("a", "") == "a"); immutable s = [1, 2]; assert(either(s, s) == s); assert(either([0, 1], [1, 2]) == [0, 1]); assert(either([0, 1], [1]) == [0, 1]); assert(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")));