public
Description: Useful add-ons for Erlang's stdlib
Homepage: right here
Clone URL: git://github.com/hassy/ngerl.git
ngerl / nglists.erl
100644 108 lines (69 sloc) 2.73 kb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
%%% @doc Additional list functions.
%%% @author Hasan Veldstra <hasan@12monkeys.co.uk>
%%% license: BSD
 
-module(nglists).
-export([count/2, deepmap/2, drop/2,
         find_first/2, find_first/3, find_last/2, find_last/3,
         init/1, pos/2, transpose/1, uniq/1, shuffle/1, random/1]).
 
-import(lists, [all/2, append/1, duplicate/2, flatten/1, foldl/3, foreach/2,
                keysort/2, map/2, nth/2, nthtail/2, reverse/1, seq/2, sum/1,
                zip/2, zipwith/3]).
 
 
%%% @doc Count the number of list items that satisfy some predicate.
 
count(Fun, L) ->
    length(lists:filter(Fun, L)).
 
 
%% @doc Like map, but maintains structure of deep lists.
 
deepmap(Fun, [H|T]) when is_list(H) -> [deepmap(Fun, H) | deepmap(Fun, T)];
deepmap(Fun, [H|T]) -> [Fun(H) | deepmap(Fun,T)];
deepmap(_Fun, []) -> [].
 
 
%% @doc Drop N elements from list L.
 
drop(N, L) when N > 0 -> nthtail(N, L);
drop(N, L) when N < 0 -> reverse(nthtail(N * -1, reverse(L)));
drop(_, L) -> L.
 
 
%% @doc Return the first element that satisfies the predicate.
%% @spec find_first(function(), list()) -> {ok, any()} | false
 
find_first(Pred, L) ->
    find_first(Pred, fun() -> false end, L).
 
%% @doc Return the value of IfNone() if no element satisfies the predicate.
%% @spec find_first(function(), function(), list()) -> {ok, any()} | any()
 
find_first(Pred, IfNone, [H|T]) ->
    case Pred(H) of
        true -> {ok, H};
        _ -> find_first(Pred, IfNone, T)
    end;
find_first(_Pred, IfNone, []) ->
    IfNone().
 
 
%% @doc Like find_first.
 
find_last(Pred, L) ->
    find_last(Pred, fun() -> false end, L).
 
%% @doc Like find_first.
 
find_last(Pred, IfNone, L) ->
    find_first(Pred, IfNone, reverse(L)).
 
 
%% @doc Drop the last element of a list.
 
init(L) -> reverse(tl(reverse(L))).
 
 
%% @doc Find the position of element E in list L.
 
pos(E, L) -> pos(E, L, 1).
pos(_, [], _) -> 0;
pos(E, [H|_], I) when E == H -> I;
pos(E, [_|T], I) -> pos(E, T, I+1).
 
 
%% @doc Transpose list.
 
transpose(L) ->
    Len = length(hd(L)),
    transpose1(L, duplicate(Len, [])).
transpose1([R|T], Acc) ->
    NewAcc = zipwith(fun(X, Y) -> Y ++ [X] end, R, Acc),
    transpose1(T, NewAcc);
transpose1([], Acc) ->
    Acc.
 
 
%% @doc Remove duplicates from list.
 
uniq([H|T]) -> [H | uniq([Y || Y <- T, Y =/= H])];
uniq([]) -> [].
 
 
%% @doc Shuffle list.
 
%% Knuth shuffle.
shuffle(L) ->
    N = length(L) * 10000,
    Pairs = map(fun(X) -> {random:uniform(N), X} end, L),
    Sorted = keysort(1, Pairs),
    map(fun({_, X}) -> X end, Sorted).
    
 
%% @doc Return an element from the list picked randomly.
 
random(L) ->
    nth(random:uniform(length(L)), L).