Обработка списка — процесс получения из терма-списка другого терма, часто тоже списка.
Список отличается следующими особенностями:
У кортежей обычно заранее известно количество внутренних элементов, поэтому их легко анализировать с помощью паттернов. В том плане, что паттерн сопоставляется с кортежем целиком. Для анализа списков паттерны тоже активно применяются, но они сопоставляются с отдельными элементами списка, а не списком целиком. Списки могут содержать тысячи и миллионы элементов, тут паттернами для списка целиком не запасёшься.
Тем не менее, конечно, Эрланг позволяет сопоставлять список целиком с паттерном.
1> ['раз', X, 'три'] = ['раз', 'два', 'три'].
['раз','два','три']
2> X.
'два'
Эффективным способом обработки списков является обработчик списка.
Для обработки списка — так, как нам нужно — можно (и часто нужно) написать свою функцию. Но сначала очень желательно посмотреть, нет ли уже готовой библиотечной функции для этих целей. Если таковая есть, надо пользоваться ею, потому что она, очень вероятно, будет работать быстрее (многие пишутся на Си). В идеале неплохо было бы помнить всё содержимое модуля lists. Но работа со списками может быть и в других библиотечных модулях, например string.
all(Pred, List) -> boolean()
Возвращает true, если каждый элемент списка удовлетворяет предикату.
any(Pred, List) -> boolean()
Возвращает true, если хотя бы один элемент списка удовлетворяет предикату.
append(ListOfLists) -> List1
Берёт сложный терм (список списков) и упрощает его: каждый элемент входит в новый единый список.
append(List1, List2) -> List3
Объединяет два списка в один.
concat(Things) -> string()
Превращает “вещи” в их текстовые представления и конкатенирует эти строки в одну. Things это список из элементов, каждый из которых: атом, строка, целое или вещественное число.
delete(Elem, List1) -> List2
Удаляет первый попавшийся элемент, который соответствует Elem из списка List1.
droplast(List) -> InitList
Удаляет последний элемент из списка.
dropwhile(Pred, List1) -> List2
Каждый элемент проверяет предикатом. Сначала отбрасывает все элементы. Как только найдётся элемент, соответствующий предикату, с этого момента все элементы списка возвращаются.
duplicate(N, Elem) -> List
Делает список из N элементов Elem.
enumerate(List1) -> List2
enumerate(Index, List1) -> List2
enumerate(Index, Step, List1) -> List2
Нумеруют список, то бишь каждый элемент превращают в кортеж. Пример:
1> lists:enumerate(['Атос', 'Портос', 'Арамис']).
[{1,'Атос'},{2,'Портос'},{3,'Арамис'}]
filter(Pred, List1) -> List2
Оставляет в списке только те элементы, которые удовлетворяют предикату.
filtermap(Fun, List1) -> List2
Фильтрует список с помощью фунтерма. Если фунтерм возвращает true или {true, Value}, элемент сохраняется.
flatlength(DeepList) -> integer() >= 0
Эквивалентно length(flatten(DeepList)), но более эффективно.
flatmap(Fun, List1) -> List2
С помощью фунтерма обрабатывается каждый элемент списка. Фунтерм должен возвращать список. Элементы этого списка добавляются в итоговый список. Таким образом, фунтерм на вход получает элемент, а возвращает несколько элементов. Пример:
1> lists:flatmap(fun(X) -> [X,X,X,X] end, [a,b,c]).
[a,a,a,a,b,b,b,b,c,c,c,c]
flatten(DeepList) -> List
flatten(DeepList, Tail) -> List
Берёт глубокий список и делает из него плоский. Примеры:
1> lists:flatten([[],[],[[],[[],[],"hello"]],[],[]]).
"hello"
2> lists:flatten([[],[],[[],[[],[],"hello"]],[],[]], " world").
"hello world"
foldl(Fun, Acc0, List) -> Acc1
Обрабатывает список с помощью фунтерма и аккумулятора. Фунтерм получает на вход очередной элемент и текущее значение аккумулятора. Acc0 — значение аккумулятора в самом начале. В итоге функция возвращает последний аккумулятор.
foldr(Fun, Acc0, List) -> Acc1
То же, что и foldl/3, но список обрабатывается справа налево.
foreach(Fun, List) -> ok
Вызывает на каждом элементе фунтерм. В итоге возвращает лишь атом ok. Используется для разного рода побочных эффектов. Например, чтобы вывести на печать каждый элемент.
join(Sep, List1) -> List2
Разбавляет список сепараторами: между всеми соседними элементами исходного списка добавляет элемент-сепаратор. Так можно, например, строку разбавить символами.
1> lists:join(32, "hello").
"h e l l o"
keydelete(Key, N, TupleList1) -> TupleList2
В списке, который состоит из кортежей, берётся каждый элемент (каждый кортеж). Если N-й элемент кортежа равен Key, этот кортеж пропускается и не попадает в итоговый список. Пример:
1> TL = lists:enumerate(['Атос', 'Портос', 'Арамис']).
[{1,'Атос'},{2,'Портос'},{3,'Арамис'}]
2> lists:keydelete(3,1,TL).
[{1,'Атос'},{2,'Портос'}]
keyfind(Key, N, TupleList) -> Tuple | false
Ищет в списке кортежей кортеж, чей N-й элемент равен Key. Возвращает этот кортеж, если таковой найден. Иначе — false.
keymap(Fun, N, TupleList1) -> TupleList2
Берет список кортежей. В каждом кортеже берёт N-й элемент и пропускает его через фунтерм Fun. Итоговый список кортежей содержит изменённые элементы.
keymember(Key, N, TupleList) -> boolean()
Берёт список кортежей, в каждом сравнивает N-й элемент с Key. Если найдётся таковой кортеж, функция возвращает true.
keymerge(N, TupleList1, TupleList2) -> TupleList3
Объединяет два списка кортежей. Предполагается, что эти списки уже отсортированы по ключу N в кортежах. Новый список кортежей получается тоже отсортированным по этому ключу. Пример:
1> TL1 = [{'бананы',6},{'мандарины',8},{'яблоки',4}].
[{'бананы',6},{'мандарины',8},{'яблоки',4}]
2> TL2 = [{'арбузы',1},{'персики',14},{'хурма',2}].
[{'арбузы',1},{'персики',14},{'хурма',2}]
3> lists:keymerge(1,TL1,TL2).
[{'арбузы',1},
{'бананы',6},
{'мандарины',8},
{'персики',14},
{'хурма',2},
{'яблоки',4}]
keyreplace(Key, N, TupleList1, NewTuple) -> TupleList2
Возвращает копию списка кортежей — за одним исключением. Первый кортеж, в котором N-й элемент равен Key, будет заменён на NewTuple.
keysearch(Key, N, TupleList) -> {value, Tuple} | false
Ищет в списке кортежей тот, чей N-й элемент равен Key. Эта функция оставлена для обратной совместимости. Обычно keyfind/3 удобнее.
keysort(N, TupleList1) -> TupleList2
Сортирует список кортежей по ключу N.
keystore(Key, N, TupleList1, NewTuple) -> TupleList2
В списке кортежей ищет тот, у которого N-й элемент равен Key. Если таковой имеется, заменяет его на NewTuple. Если такового нет, дописывает NewTuple в конец списка кортежей.
keytake(Key, N, TupleList1) -> {value, Tuple, TupleList2} | false
В списке кортежей ищет тот, у которого N-й элемент равен Key. При наличии такового возвращает {value, Tuple, TupleList2}, где Tuple — найденный кортеж, а TupleList2 — новый список кортежей, из которого был изъят Tuple (только один, первый найденный).
last(List) -> Last
Возвращает последний элемент списка.
map(Fun, List1) -> List2
Каждый элемент списка пропускает через фунтерм. Из новых значений формируется новый список — с таким же количеством элементов.
mapfoldl(Fun, Acc0, List1) -> {List2, Acc1}
Комбинация map/2 и foldl/3 — за один проход. То есть и пропускает через фунтерм каждый элемент списка, и при этом делает свёртку, возвращая аккумулятор. Действует слева направо.
mapfoldr(Fun, Acc0, List1) -> {List2, Acc1}
Как mapfoldl/3, только справа налево.
max(List) -> Max
Возвращает наибольший элемент списка.
member(Elem, List) -> boolean()
Проверяет, есть ли такой элемент в списке.
merge(ListOfLists) -> List1
merge(List1, List2) -> List3
merge(Fun, List1, List2) -> List3
merge3(List1, List2, List3) -> List4
Возвращает объединённый отсортированный список.
min(List) -> Min
Возвращает минимальный элемент.
nth(N, List) -> Elem
Возвращает N-й элемент списка.
nthtail(N, List) -> Tail
Возвращает хвост списка — то, что после N-го элемента.
partition(Pred, List) -> {Satisfying, NotSatisfying}
Список с помощью предиката делится на два. Элементы первого удовлетворяют предикату, элементы второго — нет.
prefix(List1, List2) -> boolean()
Если List1 является префиксом списка List2, будет true.
reverse(List1) -> List2
Возвращает список в обратном порядке.
reverse(List1, Tail) -> List2
Возвращает развернутый в другую сторону список вместе с добавленным хвостом.
search(Pred, List) -> {value, Value} | false
Если какое-то значение (элемент) списка удовлетворяет предикату, возвращается в кортеже с пометкой value.
seq(From, To) -> Seq
seq(From, To, Incr) -> Seq
Возвращает список — последовательность целых чисел от From до To. Если указан Incr, то с этим шагом.
sort(List1) -> List2
sort(Fun, List1) -> List2
Сортирует элементы. Можно указать сортирующий фунтерм, который принимает два аргумента, A и B. Если A<=B
, фунтерм должен вернуть true. Иначе — false.
split(N, List1) -> {List2, List3}
Разделяет список на два. List2 содержит первый N элементов. Остальные достаются List3.
splitwith(Pred, List) -> {List1, List2}
Делит список на две части с помощью предиката. Пока элементы удовлетворяют предикату, они попадают в первый список. Все остальные (включая те, которые тоже удовлетворяют предикату) попадают во второй список.
sublist(List1, Len) -> List2
sublist(List1, Start, Len) -> List2
Возвращает часть списка. Если указать Start, то с этой позиции, иначе с 1-й. Len — длина подсписка. Если она окажется слишком большой, это не будет ошибка, просто вернётся всё до конца исходного списка.
subtract(List1, List2) -> List3
Перебирает элементы из List2. Для каждого из них ищет первое появление в List1 и удаляет его. Пример:
1> lists:subtract("abcdabcabc", "cac").
"bdababc"
suffix(List1, List2) -> boolean()
Если List1 является суффиксом у List2, возвращается true. Иначе false. Пример:
1> lists:suffix("щик", "Паромщик").
true
sum(List) -> number()
Возвращает сумму элементов (которые числа).
takewhile(Pred, List1) -> List2
Возвращает префикс — все первые элементы, которые удовлетворяют предикату.
ukeymerge(N, TupleList1, TupleList2) -> TupleList3
Объединяет два списка отсортированных кортежей в третий — тоже отсортированный. Сортировка осуществляется по N-му элементу. Подразумевается, что оба исходных списка кортежей уже отсортированы по N-му элементу.
ukeysort(N, TupleList1) -> TupleList2
Сортирует список кортежей по N-му элементу, при этом удаляя дубли.
umerge(ListOfLists) -> List1
umerge(List1, List2) -> List3
umerge(Fun, List1, List2) -> List3
umerge3(List1, List2, List3) -> List4
Возвращает отсортированное объединение списков.
uniq(List1) -> List2
uniq(Fun, List1) -> List2
Удаляет дубли, сохраняя порядок элементов. Из одинаковых элементов сохраняется первый.
unzip(List1) -> {List2, List3}
unzip3(List1) -> {List2, List3, List4}
“Расстёгивает” список кортежей, каждый из которых состоит из двух (или трёх) элементов. Из первых элементов образуется List2, из вторых — List3.
usort(List1) -> List2
usort(Fun, List1) -> List2
Возвращает список, состоящий из отсортированных уникальных элементов.
zip(List1, List2) -> List3
zip(List1, List2, How) -> List3
zip3(List1, List2, List3) -> List4
zip3(List1, List2, List3, How) -> List4
“Застёгивает” два (или три) списка в список кортежей, каждый из которых состоит из двух (или трёх) элементов. Первые элементы кортежей берутся из первого списка. Вторые — из второго. Атрибут How определяет, как себя ведёт “застёгивание” в нестандартных случаях.
zipwith(Combine, List1, List2) -> List3
zipwith(Combine, List1, List2, How) -> List3
zipwith3(Combine, List1, List2, List3) -> List4
zipwith3(Combine, List1, List2, List3, How) -> List4
Комбинирует элементы из двух (или трёх) списков в один с помощью фунтерма Combine.
Модуль lists — официальная документация.
© Алексей Карманов, 2024.