std/algorithm
Исходный кодРедактироватьЭтот модуль реализует некоторые общие обобщённые алгоритмы над openArray.
Основные примеры использования
Пример:
import std/algorithm
type People = tuple
year: int
name: string
var a: seq[People]
a.add((2000, "John"))
a.add((2005, "Marie"))
a.add((2010, "Jane"))
# Sorting with default system.cmp
a.sort()
assert a == @[(year: 2000, name: "John"), (year: 2005, name: "Marie"),
(year: 2010, name: "Jane")]
proc myCmp(x, y: People): int =
cmp(x.name, y.name)
# Sorting with custom proc
a.sort(myCmp)
assert a == @[(year: 2010, name: "Jane"), (year: 2000, name: "John"),
(year: 2005, name: "Marie")] См. также
- модуль sequtils для работы с встроенным типом seq
- модуль tables для сортировки таблиц
Импорты
- since
Типы
SortOrder = enum Descending, Ascending
- Исходный код Редактировать
Процедуры
proc `*`(x: int; order: SortOrder): int {.inline, ...raises: [], tags: [], forbids: [].}-
Изменяет знак
xеслиorder == Descending. Еслиorder == Ascendingто возвращаетсяx.xдолжен быть результатом компаратора, т.е.< 0для меньше чем,== 0для равно,> 0для больше чем.Пример:
assert -123 * Descending == 123 assert 123 * Descending == -123 assert -123 * Ascending == -123 assert 123 * Ascending == 123
Исходный код Редактировать proc binarySearch[T, K](a: openArray[T]; key: K; cmp: proc (x: T; y: K): int {.closure.}): int {. effectsOf: cmp.}-
Бинарный поиск
keyвa. Возвращает индексkeyили -1, если не найдено. Предполагается, чтоaотсортирован в соответствии сcmp.cmp- функция компаратора, ожидаемые значения возврата такие же, как у system.cmp.Пример:
assert binarySearch(["a", "b", "c", "d"], "d", system.cmp[string]) == 3 assert binarySearch(["a", "b", "c", "d"], "c", system.cmp[string]) == 2
Исходный код Редактировать proc binarySearch[T](a: openArray[T]; key: T): int
- Бинарный поиск
keyвa. Возвращает индексkeyили -1, если не найдено. Предполагается, чтоaотсортирован.Пример:
assert binarySearch([0, 1, 2, 3, 4], 4) == 4 assert binarySearch([0, 1, 2, 3, 4], 2) == 2
Исходный код Редактировать proc fill[T](a: var openArray[T]; first, last: Natural; value: T)
-
Присваивает
valueвсем элементам срезаa[first..last].Если передан недопустимый диапазон, генерируется исключение
IndexDefect.Пример:
var a: array[6, int] a.fill(1, 3, 9) assert a == [0, 9, 9, 9, 0, 0] a.fill(3, 5, 7) assert a == [0, 9, 9, 7, 7, 7] doAssertRaises(IndexDefect, a.fill(1, 7, 9))
Исходный код Редактировать proc fill[T](a: var openArray[T]; value: T)
- Присваивает
valueвсем элементам контейнераa.Пример:
var a: array[6, int] a.fill(9) assert a == [9, 9, 9, 9, 9, 9] a.fill(4) assert a == [4, 4, 4, 4, 4, 4]
Исходный код Редактировать func isSorted[T](a: openArray[T]; cmp: proc (x, y: T): int {.closure.}; order = SortOrder.Ascending): bool {.effectsOf: cmp.}-
Проверяет, отсортирован ли
aвorderс использованиемcmpдля сравнения. Параметры идентичныsort. Требует O(n) времени.См. также:
Пример:
let a = [2, 3, 1, 5, 4] b = [1, 2, 3, 4, 5] c = [5, 4, 3, 2, 1] d = ["adam", "brian", "cat", "dande"] e = ["adam", "dande", "brian", "cat"] assert isSorted(a) == false assert isSorted(b) == true assert isSorted(c) == false assert isSorted(c, Descending) == true assert isSorted(d) == true assert isSorted(e) == false
Исходный код Редактировать proc isSorted[T](a: openArray[T]; order = SortOrder.Ascending): bool
-
Сокращённая версия
isSorted, которая используетsystem.cmp[T]в качестве функции сравнения.См. также:
Пример:
let a = [2, 3, 1, 5, 4] b = [1, 2, 3, 4, 5] c = [5, 4, 3, 2, 1] d = ["adam", "brian", "cat", "dande"] e = ["adam", "dande", "brian", "cat"] assert isSorted(a) == false assert isSorted(b) == true assert isSorted(c) == false assert isSorted(c, Descending) == true assert isSorted(d) == true assert isSorted(e) == false
Исходный код Редактировать proc lowerBound[T, K](a: openArray[T]; key: K; cmp: proc (x: T; k: K): int {.closure.}): int {. effectsOf: cmp.}-
Возвращает индекс первого элемента в
a, который не меньше (т.е. больше или равен)key, или последнего, если такого элемента нет. Другими словами, если у вас отсортированная последовательность и вы вызываетеinsert(thing, elm, lowerBound(thing, elm)), последовательность по-прежнему будет отсортирована. Предполагается, чтоaотсортирован в соответствии сcmp.Если передан недопустимый диапазон, генерируется исключение
IndexDefect.Этот вариант использует
cmpдля сравнения элементов. Ожидаемые значения возврата такие же, как уsystem.cmp.См. также:
-
upperBound proc отсортировано по
cmpв указанном порядке - upperBound proc
Пример:
var arr = @[1, 2, 3, 5, 6, 7, 8, 9] assert arr.lowerBound(3, system.cmp[int]) == 2 assert arr.lowerBound(4, system.cmp[int]) == 3 assert arr.lowerBound(5, system.cmp[int]) == 3 arr.insert(4, arr.lowerBound(4, system.cmp[int])) assert arr == [1, 2, 3, 4, 5, 6, 7, 8, 9]
Исходный код Редактировать -
upperBound proc отсортировано по
proc lowerBound[T](a: openArray[T]; key: T): int
-
Возвращает индекс первого элемента в
a, который не меньше (т.е. больше или равен)key, или последнего, если такого элемента нет. Другими словами, если у вас отсортированная последовательность и вы вызываетеinsert(thing, elm, lowerBound(thing, elm)), последовательность по-прежнему будет отсортирована. Предполагается, чтоaотсортирован.Этот вариант использует функцию сравнения по умолчанию
cmp.См. также:
-
upperBound proc отсортировано по
cmpв указанном порядке - upperBound proc
-
upperBound proc отсортировано по
proc merge[T](result: var seq[T]; x, y: openArray[T]) {.inline.}-
Сокращённая версия
merge, которая используетsystem.cmp[T]в качестве функции сравнения.См. также:
Пример:
let x = [5, 10, 15, 20, 25] let y = [50, 40, 30, 20, 10].sorted var merged: seq[int] merged.merge(x, y) assert merged.isSorted assert merged == @[5, 10, 10, 15, 20, 20, 25, 30, 40, 50]
Исходный код Редактировать proc merge[T](result: var seq[T]; x, y: openArray[T]; cmp: proc (x, y: T): int {.closure.}) {.effectsOf: cmp.}- Объединяет две отсортированные
openArray.xиyпредполагаются отсортированными. Если вы не хотите предоставлять свойcmp, вы можете использоватьsystem.cmpили вместо этого вызвать перегруженную версиюmerge, которая используетsystem.cmp.Примечание: Исходные данныеresultне очищаются, новые данные добавляются кresult.См. также:
Пример:
let x = @[1, 3, 6] let y = @[2, 3, 4] block: var merged = @[7] # new data is appended to merged sequence merged.merge(x, y, system.cmp[int]) assert merged == @[7, 1, 2, 3, 3, 4, 6] block: var merged = @[7] # if you only want new data, clear merged sequence first merged.setLen(0) merged.merge(x, y, system.cmp[int]) assert merged.isSorted assert merged == @[1, 2, 3, 3, 4, 6] import std/sugar var res: seq[(int, int)] res.merge([(1, 1)], [(1, 2)], (a, b) => a[0] - b[0]) assert res == @[(1, 1), (1, 2)] assert seq[int].default.dup(merge([1, 3], [2, 4])) == @[1, 2, 3, 4]
Исходный код Редактировать proc nextPermutation[T](x: var openArray[T]): bool {.discardable.}-
Вычисляет следующее лексикографическое перестановку, непосредственно изменяя
x. Результат — произошла ли перестановка, иначе мы достигли последней упорядоченной перестановки.Если вы начинаете с неупорядоченного массива/последовательности, повторяющиеся перестановки не дадут вам все перестановки, но остановятся на последней.
См. также:
Пример:
var v = @[0, 1, 2, 3] assert v.nextPermutation() == true assert v == @[0, 1, 3, 2] assert v.nextPermutation() == true assert v == @[0, 2, 1, 3] assert v.prevPermutation() == true assert v == @[0, 1, 3, 2] v = @[3, 2, 1, 0] assert v.nextPermutation() == false assert v == @[3, 2, 1, 0]
Исходный код Редактировать proc prevPermutation[T](x: var openArray[T]): bool {.discardable.}-
Вычисляет предыдущее лексикографическое перестановку, непосредственно изменяя
x. Результат — произошла ли перестановка, иначе мы достигли первой упорядоченной перестановки.См. также:
Пример:
var v = @[0, 1, 2, 3] assert v.prevPermutation() == false assert v == @[0, 1, 2, 3] assert v.nextPermutation() == true assert v == @[0, 1, 3, 2] assert v.prevPermutation() == true assert v == @[0, 1, 2, 3]
Исходный код Редактировать proc product[T](x: openArray[seq[T]]): seq[seq[T]]
- Производит декартово произведение массива. Каждый элемент результата — комбинация одного элемента из каждой последовательности в
x, где i-й элемент берется изx[i].Предупреждение: сложность может увеличиться.Пример:
assert product(@[@[1], @[2]]) == @[@[1, 2]] assert product(@[@["A", "K"], @["Q"]]) == @[@["K", "Q"], @["A", "Q"]]
Исходный код Редактировать
proc reverse[T](a: var openArray[T])
-
Обращает содержимое контейнера
a.См. также:
-
процедура reversed обращает срез и возвращает
seq[T] -
процедура reversed обращает и возвращает
seq[T]
Пример:
var a = [1, 2, 3, 4, 5, 6] a.reverse() assert a == [6, 5, 4, 3, 2, 1] a.reverse() assert a == [1, 2, 3, 4, 5, 6]
Исходный код Редактировать -
процедура reversed обращает срез и возвращает
proc reverse[T](a: var openArray[T]; first, last: Natural)
-
Обращает срез
a[first..last].Если передан недопустимый диапазон, генерируется
IndexDefect.См. также:
-
процедура reversed обращает срез и возвращает
seq[T] -
процедура reversed обращает и возвращает
seq[T]
Пример:
var a = [1, 2, 3, 4, 5, 6] a.reverse(1, 3) assert a == [1, 4, 3, 2, 5, 6] a.reverse(1, 3) assert a == [1, 2, 3, 4, 5, 6] doAssertRaises(IndexDefect, a.reverse(1, 7))
Исходный код Редактировать -
процедура reversed обращает срез и возвращает
proc reversed[T](a: openArray[T]): seq[T] {.inline.}-
Возвращает элементы
aв обратном порядке.См. также:
Пример:
assert [10, 11, 12].reversed == @[12, 11, 10] assert seq[string].default.reversed == @[]
Исходный код Редактировать proc reversed[T](a: openArray[T]; first: Natural; last: int): seq[T] {.inline, ...deprecated: "use: `reversed(toOpenArray(a, first, last))`".}- Исходный код Редактировать
proc rotatedLeft[T](arg: openArray[T]; dist: int): seq[T]
-
То же, что и
rotateLeft, только с разницей, что не изменяет аргумент. Вместо этого создает новыйseq.См. также:
- процедура rotateLeft для in-place версии этой процедуры
- процедура rotatedLeft для версии, которая вращает диапазон
Пример:
var a = @[1, 2, 3, 4, 5] a = rotatedLeft(a, 2) assert a == @[3, 4, 5, 1, 2] a = rotatedLeft(a, 4) assert a == @[2, 3, 4, 5, 1] a = rotatedLeft(a, -6) assert a == @[1, 2, 3, 4, 5]
Исходный код Редактировать proc rotatedLeft[T](arg: openArray[T]; slice: HSlice[int, int]; dist: int): seq[ T]-
То же, что и
rotateLeft, только с разницей, что не изменяет аргумент. Вместо этого создает новыйseq.Элементы за пределами
sliceостанутся неизменными. Если передан недопустимый диапазон (HSlice), генерируетсяIndexDefect.slice- Индексы диапазона элементов, которые должны быть повернуты.
dist- Расстояние в количестве элементов, на которое должны быть повернуты данные. Может быть отрицательным, может быть любым числом.
См. также:
- процедура rotateLeft для in-place версии этой процедуры
- процедура rotatedLeft для версии, которая вращает весь контейнер
Пример:
var a = @[1, 2, 3, 4, 5] a = rotatedLeft(a, 1 .. 4, 3) assert a == @[1, 5, 2, 3, 4] a = rotatedLeft(a, 1 .. 3, 2) assert a == @[1, 3, 5, 2, 4] a = rotatedLeft(a, 1 .. 3, -2) assert a == @[1, 5, 2, 3, 4]
Исходный код Редактировать proc rotateLeft[T](arg: var openArray[T]; dist: int): int {.discardable.}-
То же, что и
rotateLeft, но с аргументами по умолчанию для среза, чтобы эта процедура работала со всемarg, а не только с частью его.См. также:
- процедура rotateLeft для версии, которая вращает диапазон
-
процедура rotatedLeft для версии, которая возвращает
seq[T]
Пример:
var a = [1, 2, 3, 4, 5] a.rotateLeft(2) assert a == [3, 4, 5, 1, 2] a.rotateLeft(4) assert a == [2, 3, 4, 5, 1] a.rotateLeft(-6) assert a == [1, 2, 3, 4, 5]
Исходный код Редактировать proc rotateLeft[T](arg: var openArray[T]; slice: HSlice[int, int]; dist: int): int {. discardable.}- Выполняет циклический сдвиг влево на диапазон элементов. Если вы хотите повернуть вправо, используйте отрицательное значение
dist. В частности,rotateLeftвращает элементы по индексамsliceнаdistпозиций.Элемент по индексу
slice.a + distбудет по индексуslice.a.
Элемент по индексуslice.bбудет по индексуslice.a + dist - 1.
Элемент по индексуslice.aбудет по индексуslice.b + 1 - dist.
Элемент по индексуslice.a + dist - 1будет по индексуslice.b.Элементы за пределами
sliceостанутся неизменными. Время выполнения пропорциональноslice.b - slice.a + 1. Если передан недопустимый диапазон (HSlice), генерируетсяIndexDefect.slice- Индексы диапазона элементов, которые должны быть повернуты.
dist- Расстояние в количестве элементов, на которое должны быть повернуты данные. Может быть отрицательным, может быть любым числом.
См. также:
- процедура rotateLeft для версии, которая вращает весь контейнер
-
процедура rotatedLeft для версии, которая возвращает
seq[T]
Пример:
var a = [0, 1, 2, 3, 4, 5] a.rotateLeft(1 .. 4, 3) assert a == [0, 4, 1, 2, 3, 5] a.rotateLeft(1 .. 4, 3) assert a == [0, 3, 4, 1, 2, 5] a.rotateLeft(1 .. 4, -3) assert a == [0, 4, 1, 2, 3, 5] doAssertRaises(IndexDefect, a.rotateLeft(1 .. 7, 2))
Исходный код Редактировать func sort[T](a: var openArray[T]; cmp: proc (x, y: T): int {.closure.}; order = SortOrder.Ascending) {.effectsOf: cmp.}-
Стандартная процедура сортировки Nim (реализация слиянием). Сортировка гарантированно устойчива (элементы с одинаковым значением сохраняют свой порядок) и в худшем случае гарантированно имеет сложность O(n log n). Сортирует по
cmpв указанномorder.Текущая реализация использует итеративный алгоритм слияния. Использует временную последовательность длиной
a.len div 2. Если вы не хотите предоставлять собственнуюcmp, вы можете использоватьsystem.cmpили вызвать перегруженную версиюsort, которая используетsystem.cmp.sort(myIntArray, system.cmp[int]) # do not use cmp[string] here as we want to use the specialized # overload: sort(myStrArray, system.cmp)
Вы можете встраивать процедуры сравнения adhoc с помощью до-нотации. Пример:
people.sort do (x, y: Person) -> int: result = cmp(x.surname, y.surname) if result == 0: result = cmp(x.name, y.name)См. также:
- процедура sort
-
процедура sorted отсортированная по
cmpв указанном порядке - процедура sorted
- шаблон sortedByIt
Пример:
var d = ["boo", "fo", "barr", "qux"] proc myCmp(x, y: string): int = if x.len() > y.len() or x.len() == y.len(): 1 else: -1 sort(d, myCmp) assert d == ["fo", "qux", "boo", "barr"]
Исходный код Редактировать proc sort[T](a: var openArray[T]; order = SortOrder.Ascending)
-
Короткая версия
sort, которая используетsystem.cmp[T]в качестве функции сравнения.См. также:
- функция sort
-
процедура sorted отсортированная по
cmpв указанном порядке - процедура sorted
- шаблон sortedByIt
proc sorted[T](a: openArray[T]; cmp: proc (x, y: T): int {.closure.}; order = SortOrder.Ascending): seq[T] {.effectsOf: cmp.}-
Возвращает
aотсортированную поcmpв указанномorder.См. также:
Пример:
let a = [2, 3, 1, 5, 4] b = sorted(a, system.cmp[int]) c = sorted(a, system.cmp[int], Descending) d = sorted(["adam", "dande", "brian", "cat"], system.cmp[string]) assert b == @[1, 2, 3, 4, 5] assert c == @[5, 4, 3, 2, 1] assert d == @["adam", "brian", "cat", "dande"]
Исходный код Редактировать proc sorted[T](a: openArray[T]; order = SortOrder.Ascending): seq[T]
-
Короткая версия
sortedкоторая используетsystem.cmp[T]в качестве функции сравнения.См. также:
Пример:
let a = [2, 3, 1, 5, 4] b = sorted(a) c = sorted(a, Descending) d = sorted(["adam", "dande", "brian", "cat"]) assert b == @[1, 2, 3, 4, 5] assert c == @[5, 4, 3, 2, 1] assert d == @["adam", "brian", "cat", "dande"]
Исходный код Редактировать
proc upperBound[T, K](a: openArray[T]; key: K; cmp: proc (x: T; k: K): int {.closure.}): int {. effectsOf: cmp.}-
Возвращает индекс первого элемента в
a, который большеkey, или последний, если такой элемент не найден. Другими словами, если у вас отсортированная последовательность, и вы вызываетеinsert(thing, elm, upperBound(thing, elm)), последовательность останется отсортированной. Предполагается, чтоaотсортирована поcmp.Если передан неверный диапазон, возникает
IndexDefect.Эта версия использует
cmpдля сравнения элементов. Ожидаемые значения возврата такие же, как уsystem.cmp.См. также:
-
процедура lowerBound отсортированная по
cmpв указанном порядке - процедура lowerBound
Пример:
var arr = @[1, 2, 3, 5, 6, 7, 8, 9] assert arr.upperBound(2, system.cmp[int]) == 2 assert arr.upperBound(3, system.cmp[int]) == 3 assert arr.upperBound(4, system.cmp[int]) == 3 arr.insert(4, arr.upperBound(3, system.cmp[int])) assert arr == [1, 2, 3, 4, 5, 6, 7, 8, 9]
Исходный код Изменить -
процедура lowerBound отсортированная по
proc upperBound[T](a: openArray[T]; key: T): int
-
Возвращает индекс первого элемента в
a, который большеkey, или последний, если такой элемент не найден. Другими словами, если у вас отсортированная последовательность, и вы вызываетеinsert(thing, elm, upperBound(thing, elm)), последовательность останется отсортированной. Предполагается, чтоaотсортирована.Эта версия использует функцию сравнения по умолчанию
cmp.См. также:
-
процедура lowerBound отсортированная по
cmpв указанном порядке - процедура lowerBound
-
процедура lowerBound отсортированная по
Шаблоны
template sortedByIt(seq1, op: untyped): untyped
-
Удобный шаблон вокруг процедуры
sortedдля уменьшения набора текста.Шаблон вставляет переменную
it, которую вы можете использовать непосредственно в выражении.Поскольку базовая процедура
cmp()определена для кортежей, вы также можете выполнить вложенную сортировку.См. также:
- функция sort
- процедура sort
-
процедура sorted отсортированная по
cmpв указанном порядке - процедура sorted
Пример:
type Person = tuple[name: string, age: int] var p1: Person = (name: "p1", age: 60) p2: Person = (name: "p2", age: 20) p3: Person = (name: "p3", age: 30) p4: Person = (name: "p4", age: 30) people = @[p1, p2, p4, p3] assert people.sortedByIt(it.name) == @[(name: "p1", age: 60), (name: "p2", age: 20), (name: "p3", age: 30), (name: "p4", age: 30)] # Nested sort assert people.sortedByIt((it.age, it.name)) == @[(name: "p2", age: 20), (name: "p3", age: 30), (name: "p4", age: 30), (name: "p1", age: 60)]Исходный код Изменить
© 2006–2024 Andreas Rumpf
Licensed under the MIT License.
https://nim-lang.org/docs/algorithm.html