From 6240f8695d08d1d061192fd0b8ca946d1a7d31ae Mon Sep 17 00:00:00 2001 From: Rain120 Date: Sun, 29 Dec 2019 11:31:49 +0800 Subject: [PATCH] feat: lodash base findIndex, find (not implementation) --- src/Algorithm/sort/radixSort/__tests__.ts | 13 +++- src/Algorithm/sort/radixSort/index.ts | 6 +- src/Array/arrayMove/index.ts | 6 +- src/Array/find/README.md | 62 +++++++++++++++ src/Array/find/__test__.ts | 12 +++ src/Array/find/index.ts | 11 +++ src/Array/isArray/index.ts | 6 +- src/lodash/.internal/__test__/__tests__.ts | 88 ++++++++++++++++++++++ src/lodash/.internal/baseFindIndex.ts | 34 +++++++++ src/types/index.d.ts | 8 +- 10 files changed, 233 insertions(+), 13 deletions(-) create mode 100644 src/Array/find/README.md create mode 100644 src/Array/find/__test__.ts create mode 100644 src/Array/find/index.ts create mode 100644 src/lodash/.internal/__test__/__tests__.ts create mode 100644 src/lodash/.internal/baseFindIndex.ts diff --git a/src/Algorithm/sort/radixSort/__tests__.ts b/src/Algorithm/sort/radixSort/__tests__.ts index db13d80..ed7ca73 100644 --- a/src/Algorithm/sort/radixSort/__tests__.ts +++ b/src/Algorithm/sort/radixSort/__tests__.ts @@ -1,8 +1,8 @@ /* * @Author: Rainy * @Date: 2019-11-14 19:25:01 - * @LastEditors: Rainy - * @LastEditTime: 2019-12-01 12:00:19 + * @LastEditors : Rainy + * @LastEditTime : 2019-12-29 11:20:52 */ import { bucketSort } from '.'; @@ -11,10 +11,19 @@ import { NumberArrayMap } from 'types'; const input: NumberArrayMap = [3, 2, 1, 2, 3, 21, 123, 312, 123, 11]; const input2: NumberArrayMap = [3, 2, 1, 2, 3, 21, 123, 312, 123, 12345, 2222, 111, 11]; + +test('bucketSort([]) should be []', () => { + expect(bucketSort([])).toEqual([]); +}); + test('bucketSort([], 0) should be []', () => { expect(bucketSort([], 0)).toEqual([]); }); +test('bucketSort([3], 1) should be [3]', () => { + expect(bucketSort([3])).toEqual([3]); +}); + test('bucketSort([3], 1) should be [3]', () => { expect(bucketSort([3], 1)).toEqual([3]); }); diff --git a/src/Algorithm/sort/radixSort/index.ts b/src/Algorithm/sort/radixSort/index.ts index 0c4f688..3e41ba3 100644 --- a/src/Algorithm/sort/radixSort/index.ts +++ b/src/Algorithm/sort/radixSort/index.ts @@ -1,8 +1,8 @@ /* * @Author: Rainy * @Date: 2019-11-14 19:25:01 - * @LastEditors: Rainy - * @LastEditTime: 2019-12-01 11:39:39 + * @LastEditors : Rainy + * @LastEditTime : 2019-12-29 11:15:28 */ import { NumberArrayMap } from 'types'; @@ -10,7 +10,7 @@ import { insertionSort } from '../insertionSort'; export function bucketSort( arr: NumberArrayMap, - bucketSize: number + bucketSize?: number, ): NumberArrayMap { if (arr.length === 0) { return arr; diff --git a/src/Array/arrayMove/index.ts b/src/Array/arrayMove/index.ts index 136681f..2c5497d 100644 --- a/src/Array/arrayMove/index.ts +++ b/src/Array/arrayMove/index.ts @@ -1,11 +1,11 @@ /* * @Author: Rainy * @Date: 2019-11-14 19:25:01 - * @LastEditors: Rainy - * @LastEditTime: 2019-11-24 20:11:42 + * @LastEditors : Rainy + * @LastEditTime : 2019-12-29 10:24:02 */ -import { AnyArrayMap } from '../../types'; +import { AnyArrayMap } from 'types'; export function arrayMove(array: AnyArrayMap, from: number, to: number): AnyArrayMap { array = array.slice(); diff --git a/src/Array/find/README.md b/src/Array/find/README.md new file mode 100644 index 0000000..8b5328f --- /dev/null +++ b/src/Array/find/README.md @@ -0,0 +1,62 @@ +> 为了不污染原生的 Array 对象, 实现通过 function 来实现 +> +> Eg: + +```javascript +// prototype +Array.prototype.find = function(predicate, /* thisArg*/) {} + +// ours +function (collection, predicate) {} +``` + +### 原理 + +`find` 方法对数组中的每一项元素执行一次 `predicate` 函数, 直至有一个 `predicate` 返回 `true`. 当找到了这样一个元素后, 该方法会立即返回这个元素的值, 否则返回 `undefined`. 注意`predicate` 函数会为数组中的每个索引调用即从 0 到 `length - 1`, 而不仅仅是那些被赋值的索引, 这意味着对于稀疏数组来说, 该方法的效率要低于那些只遍历有值的索引的方法. + +- 把传入的 `this` 转换成 `Object`对象, 需要`null`值处理 -> `O` + +- 取出 `Object`的 `length` -> `len` + +- 判断传入 `predicate` 的是否是 `function`, 抛出异常 `TypeError exception` + +- 设置计数器 `k = 0` + +- `while k < len` + - `kValue = O[k]` + - `testResult = predicate(thisArg, kValue, k, O)` -> `Boolean` + - `testResult is true, return kValue` + - `Set k to k + 1` +- `Return undefined` + +### 参数 + +- `predicate` + + 在数组每一项上执行的函数, 接收 3 个参数: + + - `element` + + 当前遍历到的元素 + + - `index` 可选 + + 当前遍历到的索引 + + - `array` 可选 + + 数组本身 + +- `thisArg` 可选 + + 执行回调时用作`this`的对象 + +### 返回值 + +返回数组中满足提供的测试函数的第一个元素的值. 否则返回 `undefined` + +### 参考 + +[Find MDN](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array/find) + +[TC39 Find](https://tc39.es/ecma262/#sec-array.prototype.find) diff --git a/src/Array/find/__test__.ts b/src/Array/find/__test__.ts new file mode 100644 index 0000000..57b77b5 --- /dev/null +++ b/src/Array/find/__test__.ts @@ -0,0 +1,12 @@ +/* + * @Author: Rainy + * @Date: 2019-11-14 19:25:01 + * @LastEditors : Rainy + * @LastEditTime : 2019-12-29 10:32:42 + */ + +import { _find } from '.'; + +// test('_isArray([]) should true', () => { +// expect(_isArray([])).toBe(true); +// }); diff --git a/src/Array/find/index.ts b/src/Array/find/index.ts new file mode 100644 index 0000000..b35a985 --- /dev/null +++ b/src/Array/find/index.ts @@ -0,0 +1,11 @@ +/* + * @Author: Rainy + * @Date: 2019-11-14 19:25:01 + * @LastEditors : Rainy + * @LastEditTime : 2019-12-29 10:31:47 + */ + +import { isAbsType } from 'utils/type'; + +export function _find(collection: any, predicate: any): any { +} diff --git a/src/Array/isArray/index.ts b/src/Array/isArray/index.ts index 37f1e9a..2c45a8c 100644 --- a/src/Array/isArray/index.ts +++ b/src/Array/isArray/index.ts @@ -1,12 +1,12 @@ /* * @Author: Rainy * @Date: 2019-11-14 19:25:01 - * @LastEditors: Rainy - * @LastEditTime: 2019-12-02 20:16:48 + * @LastEditors : Rainy + * @LastEditTime : 2019-12-29 11:09:21 */ import { isAbsType } from '../../utils/type'; export function _isArray(target: any): boolean { - return isAbsType(target).toLowerCase() === 'array'; + return isAbsType(target).toLowerCase() === 'array'; } diff --git a/src/lodash/.internal/__test__/__tests__.ts b/src/lodash/.internal/__test__/__tests__.ts new file mode 100644 index 0000000..73ef839 --- /dev/null +++ b/src/lodash/.internal/__test__/__tests__.ts @@ -0,0 +1,88 @@ +/* + * @Author: Rainy + * @Date: 2019-12-29 10:44:01 + * @LastEditors : Rainy + * @LastEditTime : 2019-12-29 11:25:32 + */ + +import { baseFindIndex } from '../baseFindIndex'; + +const input: any = [1, 2, 3, 3, 4, 5, 6, 7]; + +const inputString: any = ['a', 'b', 'c']; + +test(`baseFindIndex(${input}, (item: any, index: number, array: any[]) => { + return item > 3; + }) should be 3`, () => { + expect( + baseFindIndex( + input, + (item: any, index: number, array: any[]) => { + return item > 3; + } + )).toEqual(4); +}); + +test(`baseFindIndex(${input}, (item: any, index: number, array: any[]) => { + return item > 2; + }) should be 2`, () => { + expect( + baseFindIndex( + input, + (item: any, index: number, array: any[]) => { + return item > 2; + } + )).toEqual(2); +}); + +test(`baseFindIndex(${input}, (item: any, index: number, array: any[]) => { + return item > 2; +}, 0) should be 2`, () => { +expect( + baseFindIndex( + input, + (item: any, index: number, array: any[]) => { + return item > 2; + }, + 0 + )).toEqual(2); +}); + +test(`baseFindIndex(${input}, (item: any, index: number, array: any[]) => { + return item > 2; +}, 4, 4) should be 4`, () => { +expect( + baseFindIndex( + input, + (item: any, index: number, array: any[]) => { + return item > 2; + }, + 4, + 4 + )).toEqual(4); +}); + +test(`baseFindIndex(${inputString}, (item: any, index: number, array: any[]) => { + return item === 'a'; + }) should be 0`, () => { + expect( + baseFindIndex( + inputString, + (item: any, index: number, array: any[]) => { + return item === 'a'; + } + )).toEqual(0); +}); + + +test(`baseFindIndex(${inputString}, (item: any, index: number, array: any[]) => { + return item === 'd'; + }) should be 0`, () => { + expect( + baseFindIndex( + inputString, + (item: any, index: number, array: any[]) => { + return item === 'd'; + } + )).toEqual(-1); +}); diff --git a/src/lodash/.internal/baseFindIndex.ts b/src/lodash/.internal/baseFindIndex.ts new file mode 100644 index 0000000..2b37072 --- /dev/null +++ b/src/lodash/.internal/baseFindIndex.ts @@ -0,0 +1,34 @@ +/* + * @Author: Rainy + * @Date: 2019-12-29 10:29:48 + * @LastEditors : Rainy + * @LastEditTime : 2019-12-29 11:31:44 + */ +import { AnyArrayMap, WithParamsReturnAnyFunction } from '../../types'; + + +/** + * @export + * @param {AnyArrayMap} array + * @param {WithParamsReturnAnyFunction} predicate + * @param {number} fromIndex + * @param {number} fromRight + * @returns {number} + */ +export function baseFindIndex( + array: AnyArrayMap, + predicate: WithParamsReturnAnyFunction, + fromIndex: number = 0, + fromRight?: number +): number { + const { length } = array; + let index = fromIndex + (fromRight ? 1 : -1); + + while ((fromRight ? --index : ++index < length)) { + if (!!predicate(array[index], index, array)) { + return index; + } + } + + return -1; +} diff --git a/src/types/index.d.ts b/src/types/index.d.ts index 5b70d14..b5c86b5 100644 --- a/src/types/index.d.ts +++ b/src/types/index.d.ts @@ -2,8 +2,8 @@ /* * @Author: Rainy * @Date: 2019-11-14 19:55:36 - * @LastEditors: Rainy - * @LastEditTime: 2019-12-01 11:57:26 + * @LastEditors : Rainy + * @LastEditTime : 2019-12-29 11:01:00 */ export class ClassType {} @@ -33,6 +33,10 @@ export type ObjectMap = { // Function export type NullFunction = () => null; +export type AnyFunction = () => any; + +export type WithParamsReturnAnyFunction = (...arg: any) => any; + export type BaseFunction = () => BaseValueType; export type MixedFunction = () => MixedValueType;