-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathArrayUtils.brs
272 lines (240 loc) · 9.56 KB
/
ArrayUtils.brs
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
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
' @import /components/getProperty.brs
' @import /components/getType.brs
' Methods to operate on arrays.
' @class
function ArrayUtils() as Object
prototype = {}
' Looks for an item, removes it from the source array and returns that item. It mutates the array. Returns Invalid when item is not found.
' @example
' ArrayUtils().pick([{ x: "a" }, { x: "b" }], function (item, desiredValue) : return (item.x = desiredValue) : end function), "b")
' ' => { x: "b" }
' @param {Dynamic[]} arrayToSearch
' @param {Function|AssociativeArray} predicate
' @param {Dynamic} [scopedData=Invalid] - Any data that is passed to predicate to deal with BrightScript variable scope.
' @returns {Dynamic} - Returns removed item. Invalid when not found.
prototype.pick = function (arrayToSearch as Object, predicate as Dynamic, scopedData = Invalid as Dynamic) as Dynamic
index = m.findIndex(arrayToSearch, predicate, scopedData)
if (index >= 0)
item = arrayToSearch[index]
arrayToSearch.delete(index)
return item
end if
return Invalid
end function
' Looks for an item in the array and returns it. Returns Invalid when item is not found.
' @param {Dynamic[]} arrayToSearch
' @param {Function|AssociativeArray} predicate
' @param {Dynamic} [scopedData=Invalid] - Any data that is passed to predicate to deal with BrightScript variable scope.
' @returns {Dynamic} - Returns the found item. Invalid when not found.
prototype.find = function (arrayToSearch as Object, predicate as Dynamic, scopedData = Invalid as Dynamic) as Dynamic
index = m.findIndex(arrayToSearch, predicate, scopedData)
if (index >= 0)
return arrayToSearch[index]
end if
return Invalid
end function
' Looks for an item in the array and returns its index.
' Warning: it does not compare node references.
' @param {Dynamic[]} arrayToSearch
' @param {Function|AssociativeArray} predicate
' @param {Dynamic} [scopedData=Invalid] - Any data that is passed to predicate to deal with BrightScript variable scope.
' @returns {Integer} - Returns item index or -1 when element is not found.
prototype.findIndex = function (arrayToSearch as Object, predicate as Dynamic, scopedData = Invalid as Dynamic) as Integer
if (arrayToSearch = Invalid)
return -1
end if
if (getType(predicate) = "roFunction")
if (scopedData <> Invalid)
for i = 0 to arrayToSearch.count() - 1
item = arrayToSearch[i]
if (predicate(item, scopedData))
return i
end if
end for
else
for i = 0 to arrayToSearch.count() - 1
item = arrayToSearch[i]
if (predicate(item))
return i
end if
end for
end if
return -1
end if
if (getType(predicate) = "roAssociativeArray")
for i = 0 to arrayToSearch.count() - 1
item = arrayToSearch[i]
if (m._objectMatchesProperties(item, predicate))
return i
end if
end for
return -1
else
for i = 0 to arrayToSearch.count() - 1
item = arrayToSearch[i]
if (getType(item) = getType(predicate) AND item = predicate)
return i
end if
end for
end if
return -1
end function
' Filters out elements from the provided array. It returns new array of items that fulfill the predicate.
' @example
' elements = ArrayUtils().filter(["dog", "cat", "fish"], function (item as String) as Boolean
' return item = "dog"
' end function))
' ?elements ' ["dog"]
' @param {Dynamic[]} arrayToSearch
' @param {Function|AssociativeArray} predicate
' @param {Dynamic} [scopedData=Invalid] - Any data that is passed to predicate to deal with BrightScript variable scope.
' @returns {Array}
prototype.filter = function (arrayToSearch as Object, predicate as Dynamic, scopedData = Invalid as Dynamic) as Object
return m._filter(arrayToSearch, predicate, scopedData, true)
end function
' Creates new array based on source array and predicate.
' @param {Dynamic[]} arrayToMap
' @param {Function|String} predicate - It can be path when array item is an object.
' @param {Dynamic} [scopedData=Invalid] - Any data that is passed to predicate to deal with BrightScript variable scope.
' @returns {Array}
prototype.map = function (arrayToMap as Object, predicate as Dynamic, scopedData = Invalid as Dynamic) as Object
mappedArray = []
if (getType(predicate) = "roFunction")
if (scopedData <> Invalid)
for each item in arrayToMap
mappedArray.push(predicate(item, scopedData))
end for
else
for each item in arrayToMap
mappedArray.push(predicate(item))
end for
end if
else if (getType(predicate) = "roString")
for each item in arrayToMap
mappedArray.push(getProperty(item, predicate))
end for
end if
return mappedArray
end function
' Determines if given array contains given element.
' @param {Dynamic[]} arrayToSearch
' @param {Function|AssociativeArray} predicate
' @param {Dynamic} [scopedData=Invalid] - Any data that is passed to predicate to deal with BrightScript variable scope.
' @returns {Boolean}
prototype.contains = function (arrayToSearch as Object, predicate as Dynamic, scopedData = Invalid as Dynamic) as Boolean
return (m.findIndex(arrayToSearch, predicate, scopedData) >= 0)
end function
' The opposite of filter method. It returns the elements of collection that predicate does not return truthy for.
' @example
' elements = ArrayUtils().reject(["dog", "cat", "fish"], function (item as String) as Boolean
' return item = "dog"
' end function))
' ?elements ' ["cat", "fish"]
' @param {Dynamic[]} arrayToSearch
' @param {Function|AssociativeArray} predicate
' @param {Dynamic} [scopedData=Invalid] - Any data that is passed to predicate to deal with BrightScript variable scope.
' @returns {Array}
prototype.reject = function (arrayToSearch as Object, predicate as Dynamic, scopedData = Invalid as Dynamic) as Object
return m._filter(arrayToSearch, predicate, scopedData, false)
end function
' Slices given array. It does not mutate source array. The endIndex is exclusive.
' @param {Dynamic[]} array
' @param {Integer} beginIndex
' @param {Integer} [endIndex=Invalid] - If not provided it returns all the left items.
' @returns {Array}
prototype.slice = function (array as Object, beginIndex as Integer, endIndex = Invalid as Dynamic) as Object
if (beginIndex > array.count() - 1)
return []
end if
if (endIndex = Invalid OR endIndex > array.count())
endIndex = array.count()
end if
slicedArray = []
for i = beginIndex to endIndex - 1
slicedArray.push(array[i])
end for
return slicedArray
end function
' Creates an array of elements, sorted in an ascending order.
' See BrightScript native method ifArraySort.SortBy
' @example
' arrayToSort = [
' { id: 3, name: "item-1" },
' { id: 2, name: "item-2" },
' { id: 1, name: "item-3" },
' ]
' sorted = ArrayUtils().sortBy(arrayToSort, function (item as Object) as Integer
' return item.id
' end function)
' ?sorted
' ' prints
' '[
' ' { id: 1, name: "item-3" },
' ' { id: 2, name: "item-2" },
' ' { id: 3, name: "item-1" },
' ']
' @param {Dynamic[]} array
' @param {Function} sortByFunction - It should return any sortable type that can be procesed by ifArraySort.SortBy function.
' @param {Dynamic} [scopedData=Invalid] - Any data that is passed to predicate to deal with BrightScript variable scope.
' @returns {Array}
prototype.sortBy = function(array as Object, sortByFunction as Function, scopedData = Invalid as Object) as Object
sortedArray = []
if (scopedData <> Invalid)
for each item in array
sortedArray.push({ item: item, fieldToSortBy: sortByFunction(item, scopedData) })
end for
else
for each item in array
sortedArray.push({ item: item, fieldToSortBy: sortByFunction(item) })
end for
end if
sortedArray.sortBy("fieldToSortBy")
return m.map(sortedArray, function (wrappedItem as Object) as Object
return wrappedItem.item
end function)
end function
' @private
prototype._filter = function (arrayToSearch as Object, predicate as Dynamic, scopedData as Dynamic, shouldMatchPredicate as Boolean) as Object
results = []
if (getType(predicate) = "roAssociativeArray")
for i = 0 to arrayToSearch.count() - 1
item = arrayToSearch[i]
if (shouldMatchPredicate = m._objectMatchesProperties(item, predicate))
results.push(item)
end if
end for
else if (getType(predicate) = "roFunction")
if (scopedData <> Invalid)
for each item in arrayToSearch
if (shouldMatchPredicate = predicate(item, scopedData))
results.push(item)
end if
end for
else
for each item in arrayToSearch
if (shouldMatchPredicate = predicate(item))
results.push(item)
end if
end for
end if
else
for each item in arrayToSearch
doesPredicateMatch = (getType(item) = getType(predicate) AND item = predicate)
if (shouldMatchPredicate = doesPredicateMatch)
results.push(item)
end if
end for
end if
return results
end function
' @private
prototype._objectMatchesProperties = function (item as Object, properties as Object) as Boolean
for each property in properties
if (item[property] <> properties[property])
return false
end if
end for
return true
end function
return prototype
end function