0%

[JavaScript] 数组方法深入研究与练习

数组是js中最常见的一种数据类型,善用正确数组的方法可以编写出良好结构的代码。

目录

回文处理

Palindromes(回文),顾名思义就是指倒着念和顺着念都是相同、前后对称的。

处理这种回文我们只需将字符串反转再进行对比,就可以得到结果啦:

1
2
3
4
5
6
7
8
9
10
function palindrome(str) {
var string = str.replace(/[\W_]/g, '').toLowerCase();
var replaceStr = string
.split('')
.reverse()
.join('');
return replaceStr === string;
}

palindrome('eye'); // true

首个单词字母大写

Title Case a Sentence(首个单词字母大写)

句中单词首字母大写, 确保字符串的每个单词首字母都大写,其余部分小写。

1
2
3
4
5
6
7
function titleCase(str) {
return str.toLowerCase().replace(/( |^)[a-z]/g, function(L) {
return L.toUpperCase();
});
}

titleCase("I'm a little tea pot"); // I'm A Little Tea Pot

思路

首先把字符串转换为小写,再用正则匹配带空格或者就字母开头的首个字母replace替换成大写字母.

返回数组最大的数字

Return Largest Numbers in Arrays(返回数组最大的数字)

找出多个数组中的最大数,并返回一个新数组

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
function largestOfFour(arr) {
// 请把你的代码写在这里
var count = [];
for (var i = 0; i < arr.length; i++) {
var a = arr[i].sort(function(a, b) {
return b - a;
});
count.push(a[0]);
}
return count;
}

largestOfFour([
[4, 5, 1, 3],
[13, 27, 18, 26],
[32, 35, 37, 39],
[1000, 1001, 857, 1]
]); // [5,27,39,1001]

思路

新定义一个数组,遍历传进来的数组进行从大到小排序,将排序后最大的数push进新的数组count最后再返回.

检查字符串结尾

Confirm the Ending(检查字符串结尾)

检查字符串结尾,判断一个字符串(str)是否以指定的字符串(target)结尾, 返回一个布尔值。

1
2
3
4
5
6
7
8
function confirmEnding(str, target) {
var lenth = str.length - target.length;
return str.substr(lenth) === target
}

confirmEnding('Connor', 'n'); // false
confirmEnding('Bastian', 'n'); // true
confirmEnding('He has to give me a new name', 'me'); // true

思路

substr()接受一个start的形参,是一个字符的索引,把字符串str.length - target.length就可以对比结尾字符串是否一样了.

重复输出字符串

Repeat a string repeat a string(重复输出字符串,复读机(雾)

重复一个指定的字符串num次,如果num是一个负数则返回一个空字符串。

对于这种题目可以使用两种方法解决:

  • 递归

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    // 第一种使用递归
    function repeat(str, num) {
    // 请把你的代码写在这里
    if (num < 0) {
    return '';
    } else if (num === 1) {
    return str;
    } else {
    return str + repeat(str, num - 1);
    }
    }

    repeat('abc', 3); // "abcabcabc"
  • while

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    function repeat(str, num) {
    var s = '';
    while (num > 0) {
    s += str;
    num--;
    }
    return s;
    }

    repeat('abc', 3);

思路

递归一般放进if()判断语句中,是一种通过重复地调用函数本身,逐次减少 num 的值来实现效果.
第二种使用了while语句,每调用一次就递减 1,直至num > 0.

截断字符串

Truncate a string(截断字符串)

截断字符串,如果字符串的长度比指定的参数 num 长,则把多余的部分用…来表示。
插入到字符串尾部的三个点号也会计入字符串的长度。如果指定的参数 num 小于或等于 3,则添加的三个点号不会计入字符串的长度。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
function truncate(str, num) {
// 首先判断num的值是不是大于字符串的长度,若是,那就没有必要省略了.
if (num >= str.length) {
return str;
}

if (num <= 3) {
return str.slice(0, num) + '...';
}

return str.slice(0, num - 3) + '...';
}

var str = 'A-tisket a-tasket A green and yellow basket';

truncate(str, str.length);

分割数组

Chunky Monkey(分割数组)

猴子吃香蕉, 分割数组,把一个数组 arr 按照指定的数组大小size分割成若干个数组块。例如:

1
2
hunk([1,2,3,4],2) => [[1,2],[3,4]];
chunk([1,2,3,4,5],2) => [[1,2],[3,4],[5]];

思路

这道题重点主要是每size个值分割一个数组,这里我们可以使用以下几种方法来解题.

  1. while + splice

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    // while + splice
    function chunk(arr, size) {
    // 定义一个新数组和用来临时存放分割的空数组.
    var a = [];
    var t = [];
    var i = 0;

    // 需要保持快照
    var len = arr.length;

    while (i < len) {
    t = arr.splice(0, size);
    a.push(t);
    i += size;
    }

    return a;
    }

    chunk([0, 1, 2, 3, 4, 5], 3);
  2. for + slice

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    // for + splice
    function chunk(arr, size) {
    var a = [],
    t = [],
    len = arr.length;

    // 数组中的个数小于size或者size是小于等于0的也就没有必要分割了
    if (len <= size || size <= 0) {
    return arr;
    } else {
    // 它的重点主要是数组中的值的数量
    for (var i = 0; i < len; i += size) {
    // 查询指定数
    t = arr.slice(i, i + size);
    a.push(t);
    }
    }
    return a;
    }

    chunk([0, 1, 2, 3, 4, 5], 3);
  3. while + slice

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    // while + slice
    function chunk(arr, size) {
    var a = [],
    t = [],
    i = 0,
    len = arr.length;

    while (i < len) {
    // 查询的值
    t = arr.slice(i, (i += size));
    a.push(t);
    }
    return a;
    }

    chunk([0, 1, 2, 3, 4, 5], 3);

过滤数组假值

Falsy Bouncer(过滤数组假值)

删除数组中的所有假值。在 JavaScript 中,假值有 falsenull0""undefinedNaN

这道题比较有意思..

一开始我走进了一个误区,想着单纯return x !== false && ...这样简单的返回就可以了,后来发现在处理NaN时会很麻烦..isNaN()还会把英文字符串也给过滤掉,再加上多个&&使得代码会变得繁乱,可读性不高.

然后查阅了一番资料后,才注意到平时被忽略Boolean()的一些特性对于处理这种类型的问题简直不能太合适.

1
2
3
4
5
6
7
8
9
10
function bouncer(arr) {
// 请把你的代码写在这里
var a = arr.filter(function(x) {
return Boolean(x);
});

return a;
}

bouncer([7, 'ate', '', false, 9]);

摘至MDN.Boolean 的描述:

如果 Boolean 构造函数的参数不是一个布尔值,则该参数会被转换成一个布尔值.如果参数是 0, -0, null, false, NaN, undefined, 或者空字符串 (“”),生成的 Boolean 对象的值为 false。其他任何值,包括任何对象或者字符串”false”, 都会创建一个值为 true 的 Boolean 对象.

摧毁指定数组

Seek and Destroy (摧毁指定数组)

实现一个摧毁(destroyer)函数,第一个参数是待摧毁的数组,其余的参数是待摧毁的值。

实现原理

filter() 为数组中的每个元素调用一次 callback函数,并利用所有使得 callback 返回 true 或 等价于 true 的值 的元素创建一个新数组.
filter()从头至尾遍历数组,若回调函数返回的是 true(通过测试),就存入新数组中.若返回的是 false,则过滤掉.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
function destroyer(arr) {
// 先将第一个参数隔开,定义一个储存着待移除的空数组
var args = arguments[0], removeArgs = [];

// 要被删除的参数装进'removeArgs'里
for (var i = 1; i < arguments.length; i++) {
removeArgs.push(arguments[i]);
}

// 遍历'args',若'removeArgs'中不存在'value',应该返回-1.反之返回false被过滤掉.
return args.filter(function(value) {
return removeArgs.indexOf(value) === -1;
});
}

destroyer([1, 2, 3, 1, 2, 3], 2, 3);

数组排序并找出元素索引

Where do I belong (数组排序并找出元素索引)

先给数组排序,然后找到指定的值在数组的位置,最后返回位置对应的索引。

举例:where([1,2,3,4], 1.5) 应该返回 1。因为 1.5 插入到数组[1,2,3,4]后变成[1,1.5,2,3,4],而 1.5 对应的索引值就是 1。

同理,where([20,3,5], 19) 应该返回 2。因为数组会先排序为 [3,5,20],19 插入到数组[3,5,20]后变成[3,5,19,20],而 19 对应的索引值就是 2。

思路

这个没啥好说的了..将第二个参数push进数组中,再进行排序.排序后通过indexOf()来实现功能.不过需要注意的是sort默认是按照’Unicode’编码进行排序的.

凯撒密码

Caesars Cipher (凯撒密码)

风靡全球的凯撒密码 Caesar cipher,又叫移位密码。移位密码也就是密码中的字母会按照指定的数量来做移位。

一个常见的案例就是 ROT13 密码,字母会移位 13 个位置。由’A’ ↔ ‘N’, ‘B’ ↔ ‘O’,以此类推。

写一个 ROT13 函数,实现输入加密字符串,输出解密字符串。所有的字母都是大写,不要转化任何非字母形式的字符(例如:空格,标点符号),遇到这些特殊字符,跳过它们。

思路

本次练习用到String.charCodeAt()String.fromCharCode(),首先来查询字符串的 Unicode 字符.

根据Unicode表我们得知:

  • < 65同时> 90对应的就是数字和小写字符a-z
  • >= 65<= 77对应的就是大写字符A-M(13 位)
  • >= 78<= 90 对应的就是大写字符N-Z

ROT13 的功能就是移位,如果序号小于 78(A-M 字母),使用 String.fromCharCode()转换成该序号加 13 的字符,反之减 13.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
function rot13(str) {
// LBH QVQ VG!
var newStr = [];

for (var i = 0; i < str.length; i++) {
// 查询每个字符串的Unicode编号
var temp = str.charCodeAt(i);
// 非大写字母,空格,数字等都不转换
if (temp < 65 || temp > 91) {
newStr.push(str.charAt(i));
continue;

// 大于77(N-Z),就转换成该序号 - 13的字符串.
} else if (temp > 77) {
newStr.push(String.fromCharCode(temp - 13));
// 小于78(A-M),就转换成该序号 + 13的字符串
} else {
newStr.push(String.fromCharCode(temp + 13));
}
}
return newStr.join('');
}

rot13('SERR PBQR PNZC'); // 你可以修改这一行来测试你的代码

Sum All Numbers in a Range

题目描述

  传递给一个包含两个数字的数组。返回这两个数字和它们之间所有数字的和。最小的数字并非总在最前面。
比如传递[1, 4]会返回10, 即1 + 2 + 3 + 4.

非数组方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
  function sumAll(arr) {
var max = Math.max.apply(null, arr);
var min = Math.min.apply(null,arr);
var num = max - min;
var total = min;

while(num) {
num--;
total += ++min;
}
return total;
}

sumAll([1, 1]);
「请笔者喝杯奶茶鼓励一下」

欢迎关注我的其它发布渠道