实现数组方法

3/13/2022 programming

# 实现原生方法

# map

Array.prototype._map = function(callback) {
    const arr = this
    const result = []
    this.forEach((val, index) => {
        result.push(callback.call(arr, val, index, arr))
    })
    return result
}
1
2
3
4
5
6
7

# reduce

Array.prototype._reduce = function(fn, initval) {
    const arr = this
    let base = typeof initval === 'undefined' ? arr[0] : initval
    let initIndex = typeof initval === 'undefined' ? 1 : 0
    arr.slice(initIndex).forEach((val, index) => {
        base = fn(base, val, initIndex + index, arr)
    })
    return base
}

1
2
3
4
5
6
7
8
9
10

# flat

Array.prototype._flat = function(depth = 1){
    let res = [...this]
    while(depth && res.some(item => Array.isArray(item))) {
        res = [].concat(...res)
        depth--
    }
    return res
}
1
2
3
4
5
6
7
8

# shuffle

实现一个全排列函数

const arr = [1, 2, 3, 4]
输出:[1, 3, 2, 4]等随机,让每一个元素在自己位置的概率是 1/4

function shuffle(arr) {
    for(let i = 0; i < arr.length; i++) {
        // 每次生成i - arr.length的随机数
        let random = Math.floor(Math.random() * (arr.length - i) + i)
        // 交换元素
        let temp = arr[i]
        arr[i] = arr[random]
        arr[random] = temp
    }
    return arr
}
1
2
3
4
5
6
7
8
9
10

# 变异考点

# 1. 将数组拍平成二维数组

let arr = [1, 2, [3, 4, 5, [6, 7], 8], 9, 10, [11, [12, 13]]]

查看答案
// 参数是拍平的深度
Array.prototype._flat = function(depth = 1){
    let len = this.maxDepLength()
    console.log(len)
    let count = len - depth < 0 ? len : len - depth
    let res = [...this]
    while(count && res.some(item => Array.isArray(item))) {
        res = [].concat(...res)
        count--
    }
    return res
}

// 计算数组深度
Array.prototype.maxDepLength = function () {
    let max = 0
    let res = 0
    for(let i = 0; i < this.length; i++) {
        if(Array.isArray(this[i])) {
            res = this[i].maxDepLength()
        }
        res = max > res ? max : res
    }
    return res + 1
}

let arr1 = arr._flat(2)
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

# 2. 将下列数组拍平

let arr = [1, 2, [3, 4, 5, [6, 7], 8], 9, 10, [11, [12, 13]]]

查看答案
function _flat(arr) {
    let result = []
    arr.forEach((val) => {
        if (!Array.isArray(val)) {
            result.push(val)
        } else {
            result = result.concat(_flat(val))
        }
    })
    return result
}

console.log(_flat(arr))
1
2
3
4
5
6
7
8
9
10
11
12
13

# 3. 计算数组深度

let arr = [1, 2, [3, 4, 5, [6, 7], 8], 9, 10, [11, [12, 13]]]

查看答案
function maxDepth(arr) {
    if (!Array.isArray(arr)) return 0
    let res = 0
    let max = 0
    arr.forEach(val => {
        res = maxDepth(val)
        max = max >= res ? max : res
    })
    return max + 1
}
1
2
3
4
5
6
7
8
9
10

# 4. 实现数组深拷贝

实现函数copy对数组或者对象进行深拷贝

let arr = [1, 2, [3, 4, 5, {a: 6, b: {c: 7}}, 8], 9, 10, [11, [12, 13]]]
const arr1 = copy(arr)
arr1[2][3].b = 2
console.log(arr)
console.log(arr1)

查看答案
function copy(value) {
    // 如果是原始数据类型就直接返回
    if (!(typeof value === 'object' && value !== null)) return value
    let result
    // 如果是数组
    if (Array.isArray(value)) {
        result = []
        value.forEach(val => {
            result.push(copy(val))
        })
    // 如果是对象
    } else if(Object.prototype.toString.call(value) === '[object Object]') {
        result = {}
        for(let key in value) {
            result[key] = copy(value[key])
        }
    }
    return result
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

# 5. 扁平化+升序不重复

已知如下数组,编写一个程序将数组扁平化去并除其中重复部分数据,最终得到一个升序且不重复的一维数组

var arr = [ [1, 2, 2], [3, 4, 5, 5], [6, 7, 8, 9, [11, 12, [12, 13, [14] ] ] ], 10]

查看答案
  1. flat扁平化
  2. 使用 Set 方法去重
  3. 升序排序
Array.from(new Set(arr.flat(Infinity))).sort((a,b) => { return a - b })
//[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14]
1
2

# 6. 两个数组合并成一个数组

请把两个数组A和B合并
var A = ['A1', 'A2', 'B1', 'B2', 'C1', 'C2', 'D1', 'D2']
var B = ['A', 'B', 'C', 'D']
合并 为 ['A1', 'A2', 'A', 'B1', 'B2', 'B', 'C1', 'C2', 'C', 'D1', 'D2', 'D']

查看答案
  1. 双指针,按照B循环
  2. 判断是否有自己的元素,有指针右移,没有在当前位置插入元素
function concatArr (arr1, arr2) {
    const arr = [...arr1]
    let curIndex = 0
    for (let i = 0; i < arr2.length; i++) {
        const RE = new RegExp(arr2[i])
        while(curIndex < arr.length) {
            ++curIndex
            if (!RE.test(arr[curIndex])) {
                arr.splice(curIndex, 0, arr2[i])
                break;
            }
        }
    }
    return arr
}
var A = ['A1', 'A2', 'B1', 'B2', 'C1', 'C2', 'D1', 'D2']
var B = ['A', 'B', 'C', 'D']
const arr = concatArr(A, B)
console.log(arr)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

# 7. 某公司1-12月的销售额对象转化成数组

某公司 1 到 12 月份的销售额存在一个对象里面,如下:
{1:222, 2:123, 5:888}
请把数据处理为如下结构:
[222, 123, null, null, 888, null, null, null, null, null, null, null]

查看答案
  1. 创建一个长度为12的数组
  2. 遍历数组,如果在对象中有元素则填入,没有返回null
  3. Array.from(obj, mapFn, thisArg) 就相当于 Array.from(obj).map(mapFn, thisArg)
  4. Array.from() (opens new window) 可以通过以下方式来创建数组对象:
    • 伪数组对象(拥有一个 length 属性和若干索引属性的任意对象)
    • 可迭代对象(可以获取对象中的元素,如 Map和 Set 等)
let obj = {
    1: 222,
    2: 123,
    5: 888
}
// Array.from
const result = Array.from({ length: 12 }).map((_, index) => obj[index + 1] || null);
// 等价于
const result = Array.from(new Array(12), (_, index) => obj[index+1] || null)
console.log(result)
1
2
3
4
5
6
7
8
9
10

# 8. 给定两个数组,写一个方法来计算它们的交集

例如:给定 nums1 = [1, 2, 2, 1],nums2 = [2, 2]
返回:[2, 2]

查看答案

注意: 这里没有用indexOf而是用的includes,因为[NaN].indexOf(NaN) === -1

var num1 = [1, 2, 2, 1]
var num2 = [2, 2, 3, 4]
var newArr2 = num1.filter((item) => {
    return num2.includes(item)
}) 
console.log(newArr2)
1
2
3
4
5
6

# 9. 给长度为10的数组分类

随机生成一个长度为 10 的整数类型的数组:
例如 [2, 10, 3, 4, 5, 11, 10, 11, 20]
将其排列成一个新数组,要求新数组形式如下
例如 [[2, 3, 4, 5], [10, 11], [20]]

查看答案
/*
1. 去重、排序
2. 用map记录,之后用values输出
*/

function formArray(arr) {
    const sortedArr = Array.from(new Set(arr)).sort((a, b) => a - b);
    const map = new Map();
    sortedArr.forEach((v) => {
        const key = Math.floor(v / 10);
        const group = map.get(key) || [];
        group.push(v);
        map.set(key, group);
    });
    return [...map.values()];
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

# 10. 把一个字符串的大小写取反

如何把一个字符串的大小写取反(大写变小写小写变大写),例如 'AbC' 变成 'aBc' const str = 'ADasfads123!@$!@#'

查看答案
function processString(s) {
    var arr = s.split('');
    var new_arr = arr.map((item) => {
        return item === item.toUpperCase() ? item.toLowerCase() : item.toUpperCase();
    });
    return new_arr.join('');
}
1
2
3
4
5
6
更新时间: 2022-04-10 13:23