UNPKG

3.42 kBtext/coffeescriptView Raw
1{curry, flip, compose, partial, _, identity,
2 unary, binary, ternary} = require "fairmont-core"
3
4{detach} = require "./object"
5{deepEqual} = require "./util"
6
7nth = curry (i, ax) -> ax[i - 1]
8first = nth 1
9second = nth 2
10third = nth 3
11fourth = nth 4
12fifth = nth 5
13last = ([rest..., last]) -> last
14rest = ([first, rest...]) -> rest
15
16# array only version of empty, not exported
17empty = (x) -> x.length == 0
18
19includes = if Array::includes
20 curry (a, ax) -> ax.includes a
21else
22 curry (a, ax) -> (ax.indexOf a ) != -1
23
24# find and findLast are defined in reactive
25# with specializations for array
26
27# curryable index variations that can use ? operator or equivalent
28# ex: if (i = findIndexOf ax, a)? then ...
29findIndexOf = curry (a, ax) -> if (i = ax.indexOf a) != -1 then i
30findLastIndexOf = curry (a, ax) -> if (i = ax.lastIndexOf a) != -1 then i
31
32# reactive `any` is preferred but `some` is faster
33some = curry binary detach Array::some
34
35# Array mutators
36push = curry (ax, a...) ->
37 ax.push a...
38 ax
39pop = detach Array::pop
40shift = detach Array::shift
41unshift = detach Array::unshift
42enqueue = unshift
43dequeue = pop
44
45# true splice without weird insertion option
46# or compose-breaking return value
47splice = curry (i, n, ax) ->
48 ax.splice i, n
49 ax
50
51insert = curry ternary (ax, a, i) ->
52 ax.splice i, 0, a
53 ax
54
55remove = curry (ax, a) ->
56 (ax.splice i, 1) if (i = ax.indexOf( a )) != -1
57 ax
58
59cat = detach Array::concat
60
61slice = curry (i, j, ax) -> ax[i...j]
62
63sort = curry binary detach Array::sort
64join = curry binary detach Array::join
65fill = curry (ax, a) -> ax.fill a
66
67# Set operations...
68
69# TODO: some of these could be implemented in terms of producers
70# TODO: update for Set type in ES6
71uniqueBy = curry (f, ax) ->
72 bx = []
73 for a in ax
74 b = f a
75 (bx.push b) unless b in bx
76 bx
77
78unique = uniq = uniqueBy identity
79
80dupes = ([a, ax...]) ->
81 if empty ax
82 []
83 else
84 bx = dupes ax
85 if a in ax && !(a in bx) then [a, bx...] else bx
86
87union = curry compose unique, cat
88
89intersection = (first, rest...) ->
90 if empty rest
91 first
92 else
93 x for x in (intersection rest...) when x in first
94
95difference = curry (ax, bx) ->
96 cx = union ax, bx
97 cx.filter (c) ->
98 (c in ax && !(c in bx)) ||
99 (c in bx && !(c in ax))
100
101complement = curry (ax, bx) -> ax.filter (c) -> !(c in bx)
102
103# https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle
104# https://github.com/pandastrike/fairmont-helpers/pull/15/commits/e0f4e1483fe925975dac2b73c20f61996e4425ee
105shuffle = (ax) ->
106 bx = cat ax
107 i = bx.length
108 unless i <= 1
109 while --i > 0
110 # the distinguishing characteristic of fisher-yates is that the random
111 # value generated is bounded by the iterator index (Math.random() * i)
112 # instead of the size of the array (Math.random() * bx.length)
113 j = Math.floor Math.random() * (i + 1)
114 [bx[i], bx[j]] = [bx[j], bx[i]]
115 if deepEqual ax, bx then shuffle ax else bx
116 else
117 bx
118
119range = curry (start, finish) -> [start..finish]
120
121{random, round} = Math
122pluck = (ax) -> ax[(round random() * (ax.length - 1))]
123
124pair = curry (a, b) -> [a, b]
125
126module.exports = {
127 first, second, third, fourth, fifth, nth, last, rest,
128 empty, includes, findIndexOf, findLastIndexOf,
129 uniqueBy, unique, uniq, dupes,
130 union, intersection, difference, complement,
131 push, pop, shift, unshift, enqueue, dequeue,
132 splice, insert, remove, cat,
133 slice, join, fill,
134 shuffle, range, pluck, pair}