-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathluciferchiu-lodash.js
3298 lines (3058 loc) · 103 KB
/
luciferchiu-lodash.js
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
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
var luciferchiu = {
//Array数组方法*********************************************************
/**
* 将数组拆分为多个size,最后剩余的会单独组成一个区块
* _.chunk(['a', 'b', 'c', 'd'], 2); => [['a', 'b'], ['c', 'd']]
* @param {array[]} array 需要处理的数组
* @param {number} size 每个块长度
* @return {result[]} 拆分后的新数组
*/
chunk: function(array, size = 1) {
return array.reduce((acuu, curr, i) => {
i % size === 0 ? acuu.push([curr]) : acuu[acuu.length - 1].push(curr);
return acuu
}, [])
},
/**
* 创建一个新数组,包含原数组中的所有非假值元素
* _.compact([0, 1, false, 2, '', 3]) => [1, 2, 3]
* @param {array[]} array 需要处理的数组
* @return {array[]} 拆分后的新数组
*/
compact: function(array) {
return array.reduce((acuu, curr, i) => {
curr ? acuu.push(curr) : void 0;
return acuu
}, [])
},
/**
* 创建一个新数组,将array与任何数组或值连接在一起
* _.concat(array, 2, [3], [[4]]) => [1, 2, 3, [4]]
* @param {array[]} array 被连接的数组
* @param {array[],number} [values] 链接的值
* @return {result[]} 连接后的的新数组
*/
concat: function(array, ...values) {
var result = []
for (let i = 0; i < array.length; i++) {
result.push(array[i])
}
for (let i = 0; i < values.length; i++) {
if (Array.isArray(values[i])) {
for (let j = 0; j < values[i].length; j++) {
result.push(values[i][j])
}
} else {
result.push(values[i])
}
}
return result
},
/**
* 创建一个新数组,将array与任何数组或值连接在一起
* _.difference([2, 1], [2, 3]) => [1]
* @param {[Array]} array [要检查的数组]
* @param {...[Array]} values [排除的值 ]
* @return {[Array]} [过滤值后的的新数组]
*/
difference: function(array, ...values) {
return array.filter(it => values.reduce((acuu, curr) => acuu.concat(curr), []).indexOf(it) == -1)
},
/**
* 接受一个 iteratee,调用array 和 values 中的每个元素以产生比较的标准
* @param {array[]} a 要检查的数组
* @param {array[]} b 排除的值
* @param {function,string} f 迭代器
* @return {array[]} 过滤值后的的新数组
*/
/**
* 接受一个 iteratee,调用array 和 values中的每个元素以产生比较的标准
* @param {[Array]} array [要检查的数组]
* @param {...[type]} args [排除的值(最后一个参数为迭代器)]
* @return {[Array]} [过滤值后的的新数组]
*/
differenceBy: function(array, ...args) {
var iterator = this.iteratee2fn(args.pop())
args = args.reduce((a, b) => a.concat(b), [])
return array.filter(it => {
for (let v of args) {
if (iterator(it) === iterator(v)) {
return false
}
}
return true
})
},
/**
* 接受一个 comparator,调用比较a,b中的元素.结果值是从第一数组中选择
* _.differenceWith([{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }], [{ 'x': 1, 'y': 2 }], _.isEqual) => [{ 'x': 2, 'y': 1 }]
* @param {[Array]} array [要检查的数组]
* @param {...[Array]} args [排除的值]
* @param [comparator] (Function) 比较器为args最后一个参数,调用两个参数(arrVal,othVal)
* @return {[type]} [返回一个过滤值后的新数组]
*/
differenceWith: function(array, ...args) {
var comparator = args.pop()
args = args.reduce((a, b) => a.concat(b), [])
return array.filter(it => {
for (let v of args) {
if (comparator(it, v)) {
return false
}
}
return true
})
},
/**
* 去除array前面的n个元素
* _.drop([1, 2, 3], 2) => [3]
* @param {[type]} array [要查询的数组]
* @param {Number} n [要去除的元素个数]
* @return {[type]} [返回array剩余切片]
*/
drop: function(array, n = 1) {
return array.reduce((acuu, curr, i) => {
i >= n ? acuu.push(curr) : void 0;
return acuu
}, [])
},
/**
* 去除array尾部的n个元素
* _.dropRight([1, 2, 3], 2) => [1]
* @param {[Array]} array [要查询的数组]
* @param {Number} n [ 要去除的元素个数]
* @return {[Array]} [返回array剩余切片]
*/
dropRight: function(array, n = 1) {
return array.reduce((acuu, curr, i) => {
i < array.length - n ? acuu.push(curr) : void 0;
return acuu
}, [])
},
/**
* 创建一个切片数组,去除array中从起点开始, predicate 返回假值结束部分
* @param {[type]} array [description]
* @param {[type]} predicate [description]
* @return {[type]} [description]
*/
dropWhile: function(array, predicate) {
var predicate = this.iteratee2fn(predicate)
var result = array.slice()
for (var i = 0; i < array.length; i++) {
if (predicate(array[i]) == false) {
break
}
result.shift()
}
return result
},
/**
* 创建一个切片数组,array中从右边开始丢,直到 predicate 返回假值结束
* @param {[Array]} array [要查询的数组]
* @param {[Function]} predicate [这个函数会在每一次迭代调用]
* @return {[Array]} [返回array剩余切片]
*/
dropRightWhile: function(array, predicate) {
var predicate = this.iteratee2fn(predicate)
var result = array.slice()
for (var i = array.length - 1; i >= 0; i--) {
if (predicate(array[i]) == false) {
break
}
result.pop()
}
return result
},
/**
* 用value填充数组
* @param {[type]} array [要填充改变的数组]
* @param {[type]} value [填充给array的值]
* @param {Number} start [开始位置]
* @param {[type]} end [结束位置]
* @return {[type]} [description]
*/
fill: function(array, value, start = 0, end = array.length) {
for (var i = start; i <= end - 1; i++) {
array[i] = value
}
return array
},
/**
* 返回第一个通过 predicate 判断为真值的元素的索引值(index)
* @param {[Array]} array [要搜索的数组]
* @param {[Array|Function|Object|string]} predicate [判断其]
* @param {number} fromIndex [开始位置索引]
* @return {[number]} [返回找到元素的 索引值(index),否则返回 -1]
*/
findIndex: function(array, predicate = this.identity, fromIndex = 0) {
for (let i = fromIndex; i < array.length; i++) {
if (this.iteratee2fn(predicate)(array[i])) {
return i
}
}
return -1
},
/**
* 返回第一个通过 predicate 判断为真值的元素的索引值(index)
* @param {[Array]} array [要搜索的数组]
* @param {[Array|Function|Object|string]} predicate [判断其]
* @param {number} fromIndex [开始位置索引]
* @return {[number]} [返回找到元素的 索引值(index),否则返回 -1]
*/
findLastIndex: function(array, predicate = this.identity, fromIndex = array.length - 1) {
for (var i = fromIndex; i >= 0; i--) {
if (this.iteratee2fn(predicate)(array[i])) return i
}
return -1
},
/**
* 减少一级array嵌套深度
* _.flatten([1, [2, [3, [4]], 5]]) => [1, 2, [3, [4]], 5]
* @param {[Array]} array [需要减少嵌套层级的数组]
* @return {[Array]} [返回减少嵌套层级后的新数组]
*/
flatten: function(array) {
return array.reduce((acuu, curr) => acuu.concat(curr), [])
},
/**
* 将array递归为一维数组
* _.flattenDeep([1, [2, [3, [4]], 5]]) => [1, 2, 3, 4, 5]
* @param {[Array]} array [需要减少嵌套层级的数组]
* @return {[Array]} [返一个的新一维数组]
*/
flattenDeep: function(array) {
return array.reduce((acuu, curr) => acuu.concat(curr instanceof Array ? this.flattenDeep(curr) : curr), [])
},
/**
* 根据depth递归减少array的嵌套层级
* @param {[type]} array [description]
* @param {Number} depth [description]
* @return {[type]} [description]
*/
flattenDepth: function(array, depth = 1) {
for (i = 1; i <= depth; i++) {
array = this.flatten(array)
}
return array
},
/**
* 返回一个由pairs构成的对象
* _.fromPairs([['fred', 30], ['barney', 40]]) => { 'fred': 30, 'barney': 40 }
* @param {[Array]} pairs [键值对]
* @return {[Object]} [返回一个新对象]
*/
fromPairs: function(pairs) {
return pairs.reduce((acuu, curr) => {
acuu[curr[0]] = curr[1];
return acuu
}, {})
},
/**
* 获取array的第一个元素
* @param {[type]} array [description]
* @return {[type]} [description]
*/
head: function(array) {
return array[0]
},
/**
* 返回首次在数组array中被找到的索引值
* @param {[type]} array [description]
* @param {[type]} value [description]
* @param {Number} fromIndex [description]
* @return {[type]} [description]
*/
indexOf: function(array, value, fromIndex = 0) {
if (fromIndex >= 0) {
for (var i = fromIndex; i < array.length; i++) {
if (array[i] === value) return i
}
} else {
for (var i = fromIndex + array.length; i < array.length; i++) {
if (array[i] === value) return i
}
}
},
/**
* 获取数组array中除了最后一个元素之外的所有元素
* _.initial([1, 2, 3]) => [1, 2]
* @param {[type]} array [description]
* @return {[type]} [description]
*/
initial: function(array) {
return array.reduce((acuu, curr, i) => {
if (i < array.length - 1) {
acuu.push(curr)
}
return acuu
}, [])
},
/**
* 求数组交集
* _.intersection([2, 1], [4, 2], [1, 2]) => [2]
* @param {...[Array]} Array [数组群]
* @return {[Array]} [返回一个包含所有传入数组交集元素的新数组]
*/
intersection: function(...arrays) {
return arrays[0].reduce((acuu, curr) => (arrays.every(it => it.includes(curr)) && acuu.push(curr), acuu), [])
},
/**
* 类似intersection,接受一个迭代器比较数组中的元素
* _.intersectionBy([2.1, 1.2], [4.3, 2.4], Math.floor) => [2.1]
* @param {...[type]} args [待检查的数组和迭代器]
* @return {[type]} [返回一个包含所有传入数组交集元素的新数组]
*/
intersectionBy: function(...args) {
var iterator = this.iteratee2fn(args.pop())
var newArgs = args.map(it => it.map(v => iterator(v)))
return args[0].reduce((acuu, curr) => (newArgs.every(it => it.includes(iterator(curr))) && acuu.push(curr), acuu), [])
},
/**
* 类似intersection,接受一个comparator调用比较arrays中的元素
* @param {...[type]} args [ 待检查的数组 & 比较器]
* @return {[type]} [返回一个包含所有传入数组交集元素的新数组]
*/
intersectionWith: function(...args) {
var comparator = args.pop()
return args[0].reduce((acuu, curr) => (args.every(it => it.some(v => comparator(v, curr))) && acuu.push(curr), acuu), [])
},
/**
* 数组转字符串用sep分开
* @param {[type]} array [要转换的数组]
* @param {String} sep [分隔元素]
* @return {[string]} [返回连接字符串]
*/
join: function(array, sep = ',') {
return array.reduce((acuu, curr, i, arr) => (i == arr.length - 1 ? acuu += curr : acuu += curr + sep, acuu), '')
},
/**
* 获取array中的最后一个元素
* @param {[type]} array [description]
* @return {[type]} [description]
*/
last: function(array) {
return array[array.length - 1]
},
/**
* 从右往左返回索引值
* @param {[type]} array [description]
* @param {[type]} value [description]
* @param {[type]} fromIndex [description]
* @return {[type]} [description]
*/
lastIndexOf: function(array, value, fromIndex = array.length - 1) {
for (i = fromIndex; i > -1; i--) {
if (array[i] === value) {
return i
}
}
return -1
},
/**
* 取array第几个元素,若是负数从最后一个开始数
* @param {[type]} array [description]
* @param {Number} n [description]
* @return {[type]} [description]
*/
nth: function(array, n = 0) {
if (n >= 0) {
return array[n]
} else {
return array[n + array.length]
}
},
/**
* 移出数组array中所有和values值相等的元素
* @param {[Array]} array [description]
* @param {...[*]} [description]
* @return {[Array]} [description]
*/
pull: function(array, ...values) {
return this.pullAllBy(array, values)
},
/**
* 类似pull,接受一个数组
* @param {[Array]} array [要修改的数组]
* @param {[Array]} values [要移除值的数组]
* @return {[Array]} [返回array]
*/
pullAll(array, values) {
return this.pullAllBy(array, values)
},
/**
* 类似pullAll,不过接受一个iteratee调用array和values的每一个值进行比较
* @param {[Array]} array [要修改的数组]
* @param {[Array]} values [要移除值的数组]
* @param {[Array|Function|Object|string]} iteratee [迭代器]
* @return {[Array]} [返回 array]
*/
pullAllBy(array, values, iteratee = this.identity) {
var iteratee = this.iteratee2fn(iteratee)
values.forEach(v => {
for (var i = 0; i < array.length; i++) {
if (iteratee(v) === iteratee(array[i])) {
array.splice(i, 1)
i--
}
}
})
return array
},
/**
* 类似pullAll,区别是这个方法接受comparator调用array和values中的值进行比较
* @param {[Array]} array [要修改的数组]
* @param {[Array]} values [要移除值的数组]
* @param {[Function]} comparator [会传入两个参数:(arrVal, othVal)]
* @return {[Array]} [返回 array]
*/
pullAllWith: function(array, values, comparator) {
values.forEach(v => {
for (var i = 0; i < array.length; i++) {
if (comparator(v, array[i])) {
array.splice(i, 1)
i--
}
}
})
return array
},
/**
* 筛选去除掉f为真的项
* @param {[type]} array [description]
* @param {[type]} f [description]
* @return {[type]} [description]
*/
remove: function(array, f) {
var result = []
for (var i = 0; i < array.length; i++) {
if (f(array[i])) {
result.push(array[i])
array.splice(i, 1)
}
}
return result
},
/**
* 颠倒数组次序
* @param {[type]} array [description]
* @return {[type]} [description]
*/
reverse: function(array) {
var l = array.length
var temp
for (var i = 0; i < l / 2; i++) {
temp = array[i]
array[i] = array[l - i - 1]
array[l - i - 1] = temp
}
return array
},
/**
* 二分搜索返回value应该插入的位置
* @param {[type]} array [description]
* @param {[type]} value [description]
* @return {[type]} [description]
*/
sortedIndex: function(array, value) {
return this.sortedIndexBy(array, value)
},
/**
* 类似sortedIndex,不过接受一个iteratee,调用每一个array元素和value值比较来计算排序
* @param {[Array]} array [要检查的排序数组]
* @param {[*]} value [要评估的值]
* @param {[Array|Function|Object|string]} iteratee [会传入一个参数:(value)]
* @return {[type]} [返回 value值 应该在数组array中插入的索引位置 index]
*/
sortedIndexBy: function(array, value, iteratee = this.identity) {
var iteratee = this.iteratee2fn(iteratee)
return sortIndex(array, 0, array.length - 1, value)
function sortIndex(array, left, right, value) {
if (left > right) {
return left
}
var mid = parseInt((left + right) / 2)
if (iteratee(array[mid]) >= iteratee(value)) {
return sortIndex(array, left, mid - 1, value)
}
if (iteratee(array[mid]) < iteratee(value)) {
return sortIndex(array, mid + 1, right, value)
}
return mid
}
},
/**
* 类似indexOf,不过是在已经排序的array上执行二分搜索
* @param {[Array]} array [要搜索的数组]
* @param {[*]} value [搜索的值]
* @return {[number]} [返回匹配值的索引位置,否则返回 -1]
*/
sortedIndexOf(array, value) {
var low = 0,
high = array.length - 1
var mid
while (low < high) {
mid = low + ((high - low) >> 1)
if (array[mid] < value) {
low = mid + 1
} else {
high = mid
}
}
if (array[low] == value) {
return low
}
return -1
},
/**
* 类似sortedIndex,不过返回最后一个索引位置
* _.sortedLastIndex([4, 5, 5, 5, 6], 5) => 4
* @param {[Array]} array [要检查的排序数组]
* @param {[*]} value [ 要评估的值]
* @return {[number]} [返回索引,不存在则返回-1]
*/
sortedLastIndex: function(array, value) {
return this.sortedLastIndexBy(array, value)
},
/**
* 类似sortedLastIndex,不过调用一个iteratee,调用每一个数组元素和value值来比较
* var objects = [{ 'x': 4 }, { 'x': 5 }]
* _.sortedLastIndexBy(objects, { 'x': 4 }, function(o) { return o.x; }); => 1
* @param {[Array]} array [要检查的排序数组]
* @param {[*]} value [要评估的值]
* @param {[Array|Function|Object|string]} iteratee [迭代函数,调用每个元素]
* @return {[number]} [返回value应该插入的位置索引]
*/
sortedLastIndexBy: function(array, value, iteratee = this.identity) {
var iterator = this.iteratee2fn(iteratee)
var low = 0,
high = array.length - 1
var mid
while (low + 1 < high) {
mid = low + ((high - low) >> 1)
if (iterator(array[mid]) <= iterator(value)) {
low = mid
} else {
high = mid - 1
}
}
if (iterator(array[high]) == iterator(value)) {
return high + 1
} else if (iterator(array[low]) == iterator(value)) {
return low + 1
}
return -1
},
/**
* 类似lastindexof,不过是在已经排序的数组上
* _.sortedLastIndexOf([4, 5, 5, 5, 6], 5) => 3
* @param {[Array]} array [要搜索的数组]
* @param {[*]} value [搜索的值]
* @return {[number]} [返回匹配值的索引位置,找不到返回-1]
*/
sortedLastIndexOf: function(array, value) {
var low = 0,
high = array.length - 1
var mid
while (low + 1 < high) {
mid = low + ((high - low) >> 1)
if (array[mid] <= value) {
low = mid
} else {
high = mid - 1
}
}
if (array[high] == value) {
return high
} else if (array[low] == value) {
return low
}
return -1
},
/**
* 类似uniq,不过是在已经排过序的数组中进行
* @param {[type]} array [description]
* @return {[type]} [description]
*/
sortedUniq: function(array) {
return Array.from(new Set(array))
},
/**
* 返回一个新数组,除了第一个元素不要
* _.tail([1, 2, 3]) => [2, 3]
* @param {[Array]} array [要检索的数组]
* @return {[Array]} [返回 array 数组的切片]
*/
tail: function(array) {
return array.reduce((acuu, curr, i) => (i > 0 ? acuu.push(curr) : void 0, acuu), [])
},
/**
* 从数组第一个元素开始提取n个元素
* @param {[Array]} array [要检索的数组]
* @param {Number} n [要提取的元素个数]
* @return {[Array]} [返回 array 数组的切片]
*/
take: function(array, n = 1) {
return array.reduce((acuu, curr, i) => i < n ? acuu.concat(curr) : acuu, [])
},
/**
* 从数组的尾部开始提取n个元素
* _.takeRight([1, 2, 3], 2) => [2, 3]
* @param {[Array]} array [要检索的数组]
* @param {Number} n [要提取的元素个数]
* @return {[Array]} [返回 array 数组的切片]
*/
takeRight(array, n = 1) {
return array.reduce((acuu, curr, i) => (i >= array.length - n && acuu.push(curr), acuu), [])
},
/**
* 从array数组的最后一个元素开始提取元素,直到 predicate 返回假值
* @param {[Array]} array [要检索的数组]
* @param {[Array|Function|Object|string]} predicate [ 每次迭代调用的函数]
* @return {[Array]} [返回 array 数组的切片]
*/
takeRightWhile: function(array, predicate = this.identity) {
var predicate = this.iteratee2fn(predicate)
var result = []
for (var i = array.length - 1; i >= 0; i--) {
if (predicate(array[i]) === false) {
break
}
result.unshift(array[i])
}
return result
},
/**
* 从array数组的起始元素开始提取元素,直到 predicate 返回假值
* @param {[Array]} array [需要处理的数组]
* @param {[Array|Function|Object|string]} predicate [每次迭代调用的函数]
* @return {[Array]} [返回 array 数组的切片]
*/
takeWhile: function(array, predicate = this.identity) {
var predicate = this.iteratee2fn(predicate)
var result = []
for (var i = 0; i < array.length - 1; i++) {
if (predicate(array[i]) === false) {
break
}
result.push(array[i])
}
return result
},
/**
* 数组并集,数组元素唯一,按顺序
* _.union([2], [1, 2]) => [2, 1]
* @param {...[arrays]} array [一系列数组]
* @return {array} [结果数组]
*/
union: function(...array) {
return this.uniq(array.reduce((pre, next) => pre.concat(next)))
},
/**
* 类似union,不过它接受一个iteratee函数,调用没一个数组的每个元素以产生唯一性标准
* @param {...[Array]} arrays [要检查的数组&迭代器]
* @return {[Array]} [返回一个新的联合数组]
*/
unionBy: function(...arrays) {
var iteratee = this.iteratee2fn(arrays.pop())
return this.uniqBy(arrays.reduce((pre, next) => pre.concat(next)), iteratee)
},
/**
* 类似union,不过它接受一个comparator函数,调用没一个数组的每个元素以产生唯一性标准
* @param {...[type]} arrays [description]
* @return {[type]} [description]
*/
unionWith: function(...arrays) {
var comparator = arrays.pop()
return this.uniqWith(arrays.reduce((pre, next) => pre.concat(next)), comparator)
},
/**
* 去除数组内重复的项
* _.uniq([2, 1, 2]) => [2, 1]
* @param {[type]} array [description]
* @return {[type]} [description]
*/
uniq: function(array) {
return Array.from(new Set(array))
},
/**
* 类似uniq,不过接受一个iteratee,调用没一个数组的每个元素产生唯一性计算标准
* @param {[Array]} array [要检查的数组]
* @param {[Array|Function|Object|string]} iteratee [迭代函数,调用每个元素]
* @return {[Array]} [返回新的去重后的数组]
*/
uniqBy: function(array, iteratee = this.identity) {
var iteratee = this.iteratee2fn(iteratee)
return array.reduce((acuu, curr) => (acuu.some(v => iteratee(v) == iteratee(curr)) ? void 0 : acuu.push(curr), acuu), [])
},
/**
* 这个方法类似union, 除了它接受一个 comparator 调用比较arrays数组的每一个元素]
* @param {[Array]} array [要检查的数组]
* @param {[Function]} comparator [比较函数,调用每个元素]
* @return {[Array]} [返回一个新的联合数组]
*/
uniqWith: function(array, comparator) {
return array.reduce((acuu, curr) => (!acuu.some(v => comparator(v, curr)) && acuu.push(curr), acuu), [])
},
/**
* 返回数组的第n个元素包含输入数组所有元素数组的第n个元素
* var zipped = _.zip(['fred', 'barney'], [30, 40], [true, false]) => [['fred', 30, true], ['barney', 40, false]]
* _.unzip(zipped) => [['fred', 'barney'], [30, 40], [true, false]]
* @param {[Array]} array [要处理的数组]
* @return {[Array]} [返回重组元素的新数组]
*/
unzip: function(array) {
return this.zip(...array)
},
/**
* 类似unzip,接受一个iteratee指定重组值如何被组合
* var zipped = _.zip([1, 2], [10, 20], [100, 200])=> [[1, 10, 100], [2, 20, 200]]
* _.unzipWith(zipped, _.add) => [3, 30, 300]
* @param {[Array]} array [要处理的分组元素数组]
* @param {[Function]} iteratee [这个函数用来组合重组的值]
* @return {[Array]} [返回重组元素的新数组]
*/
unzipWith: function(array, iteratee = this.identity) {
return this.unzip(array).reduce((acuu, curr) => (acuu.push(iteratee(...curr)), acuu), [])
},
/**
* 给出array剔除values一系列值的数组
* @param {[type]} array [要检查的数组]
* @param {...[type]} values [一系列单个值]
* @return {[type]} [过滤值后的数组]
*/
without: function(array, ...values) {
return array.filter(ele => !values.some(curr => curr === ele))
},
/**
* 求数组差集
* _.xor([2, 1], [2, 3]) => [1, 3]
* @param {...[Array]} array [要检查的数组]
* @return {[Array]} [返回过滤值后的新数组]
*/
xor: function(...array) {
return array.reduce((a, b) => a.concat(b)).reduce(function(acuu, curr, i, arr) {
var temp = arr.slice()
temp.splice(i, 1)
temp.includes(curr) ? void 0 : acuu.push(curr)
return acuu
}, [])
},
/**
* 类似xor,不过接受一个迭代器,以生成比较值
* @param {...[Array]} args [要检查的数组,最后一个参数为迭代器]
* @return {[Array]} [返回过滤值后的新数组]
*/
xorBy: function(...args) {
var iteratee = this.iteratee2fn(args.pop())
var iterArr = this.flatten(args).map(it => iteratee(it))
return this.flatten(args).reduce((acuu, curr, i, arr) => {
var temp = iterArr.slice()
temp.splice(i, 1)
temp.includes(iteratee(curr)) ? void 0 : acuu.push(curr)
return acuu
}, [])
},
/**
* 和xor类似,接受一个comparator,以调研比较数组的元素。
* @param {...[Array]} args [要检查的数组,最后一个参数为比较器]
* @return {[Array]} [返回过滤值后的新数组]
*/
xorWith: function(...args) {
var comparator = args.pop()
return this.flatten(args).reduce((acuu, curr, i, arr) => {
var temp = arr.slice()
temp.splice(i, 1)
temp.some(v => comparator(v, curr)) ? void 0 : acuu.push(curr)
return acuu
}, [])
},
/**
* 创建一个分组元素的数组,数组的第n个元素包含所有给定数组的第n个元素
* @param {...[type]} arg [description]
* @return {[type]} [description]
*/
zip: function(...arg) {
return arg[0].reduce((acuu, curr, i) => (acuu.push(arg.reduce((pre, next) => pre.concat(next[i]), [])), acuu), [])
},
/**
* 类似zip,不过接受一个iteratee,来指定分组的值该如何被组合。该iteratee调用每个组的元素: (...group).
* @param {...[Array]} arg [要处理的数组,最后一个参数为iteratee]
* @return {[Array]} [返回分组元素的新数组]
*/
zipWith: function(...arg) {
var iteratee = this.iteratee2fn(arg.pop())
return arg[0].reduce((acuu, curr, i) => (acuu.push(iteratee(...arg.reduce((pre, next) => (pre.push(next[i]), pre), []))), acuu), [])
},
/**
* 第一组数组作为属性名,第二组为对应属性值
* @param {Array} props [description]
* @param {Array} values [description]
* @return {[type]} [description]
*/
zipObject: function(props = [], values = []) {
var result = {}
for (var i in props) {
result[props[i]] = values[i]
}
return result
},
/**
* 类似zipObject,但它支持属性路径
* @param {Array} props [description]
* @param {Array} values [description]
* @return {[type]} [description]
*/
zipObjectDeep(props = [], values = []) {
var result = {}
for (var i in props) {
var path = props[i].split(/\.|(?=\[)/) //.map(curr => curr.indexOf('[')!=-1 && curr.indexOf(']')!=-1 ? curr.replace(/\[|\]/g,''):curr)
var temp = result
for (var j = 0; j < path.length; j++) {
if (j != path.length - 1 && path[j + 1].indexOf('[') !== -1 && path[j + 1].indexOf(']') !== -1) {
temp[path[j]] == undefined ? temp[path[j]] = [] : void 0
} else if (path[j].indexOf('[') !== -1 && path[j].indexOf(']') !== -1) {
path[j] = path[j].replace(/\[|\]/g, '')
temp[path[j]] == undefined ? temp[path[j]] = {} : void 0
} else {
temp[path[j]] == undefined ? temp[path[j]] = {} : void 0
}
if (j == path.length - 1) {
temp[path[j]] = values[i]
}
temp = temp[path[j]]
}
}
return result
},
//Collection集合方法*******************************************************
/**
* 创建一个组成对象,key是iteratee调用每个元素返回的结果,value是出现的次数
* _.countBy([6.1, 4.2, 6.3], Math.floor) => { '4': 1, '6': 2 }
* @param {[Array|Object]} collection [一个用来迭代的集合]
* @param {[Array|Function|Object|string]} iteratee [一个迭代函数,用来转换key]
* @return {[Object]} [返回一个组成集合对象]
*/
countBy: function(collection, iteratee = this.identity) {
var iteratee = this.iteratee2fn(iteratee)
var result = {}
for (var key of collection) {
if (result[iteratee(key)]) {
result[iteratee(key)]++
} else {
result[iteratee(key)] = 1
}
}
return result
},
/**
* 通过predicat检查collection中的元素是否都返回真值。一旦predicate返回假值,停止迭代。
* _.every([true, 1, null, 'yes'], Boolean) => false
* @param {[Array|Object]} collection [一个用来迭代的集合]
* @param {[Array|Function|Object|string]} predicate [每次迭代调用的函数]
* @return {[boolean]} [是否都满足]
*/
every: function(collection, predicate = this.identity) {
var predicate = this.iteratee2fn(predicate)
for (let key in collection) {
if (predicate(collection[key], key, collection) === false) {
return false
}
}
return true
},
/**
* 类似数组filter
* @param {[Array|Object]} collection [ 一个用来迭代的集合]
* @param {[Array|Function|Object|string]} predicate [每次迭代调用的函数]
* @return {[Array]} [返回一个新的过滤后的数组]
*/
filter: function(collection, predicate = this.identity) {
var predicate = this.iteratee2fn(predicate)
var result = []
for (let key in collection) {
if (predicate(collection[key], key, collection) === true) {
result.push(collection[key])
}
}
return result
},
/**
* 遍历collection,返回predicate第一次返回真值的第一个元素
* @param {[Array|Object]} collection [一个用来迭代的集合]
* @param {[Array|Function|Object|string]} predicate [ 每次迭代调用的函数]
* @param {Number} fromIndex [开始搜索的索引位置]
* @return {[*]} [返回匹配元素,否则返回 undefined]
*/
find: function(collection, predicate = this.identity, fromIndex = 0) {
var predicate = this.iteratee2fn(predicate)
for (var key in collection) {
if (Array.isArray(collection)) {
if (key < fromIndex) {
continue
}
}
if (predicate(collection[key], key, collection)) {
return collection[key]
}
}
},
/**
* 类似find,从右向左
* _.findLast([1, 2, 3, 4], function(n) {return n % 2 == 1;}) => 3
* @param {[Array|Object]} collection [一个用来迭代的集合]
* @param {[Array|Function|Object|string]} predicate [每次迭代调用的函数]
* @param {[number]} fromIndex [开始搜索的索引位置]
* @return {[*]} [返回匹配元素,否则返回 undefined]
*/
findLast: function(collection, predicate = this.identity, fromIndex = collection.length) {
var predicate = this.iteratee2fn(predicate)
var keys = Object.keys(collection)
for (var i = fromIndex; i >= 0; i--) {
if (predicate(collection[keys[i]], keys[i], collection)) {
return collection[keys[i]]
}
}
},
/**
* [创建一个扁平化数组,这个数组的值来自集合中每个值经iteratee跌倒后返回的结果]
* @param {[Array|Object]} collection [一个用来迭代遍历的集合]
* @param {[Array|Function|Object|string]} iteratee [每次迭代调用的函数]
* @return {[Array]} [返回新扁平化数组]
*/
flatMap(collection, iteratee = this.identity) {
var iteratee = this.iteratee2fn(iteratee)
var result = []
for (var key in collection) {