好久不见:这是一份常用的javascript简易算法

作为一个曾经的ruby后端,我在学习javascript时经历了不少挫折。像merge,flatten,uniq这些基础方法貌似都从我的视线中消失了。

然后我发现了loadsh, 嗯,它非常酷…,直到我发现在更新新版本的时候需要非常注意,一些重要方法中的变动导致的风险(当然发生过,想象一下当你在调试(debug)你的代码时loadsh改变了一个方法,几乎跟之前的完全不一样了,那个酸爽!更惊喜的是你甚至在最开始都没发现loadsh已经更新了!2333)

多年以后,感谢全新的es6标准让事情变的更简单了,我几乎很少使用loadsh或者其他基础算法库了。以下是我在写代码时常用的但并不很全面的一些算法。

免责声明:我并不是说loadsh在效率或者算法复杂度方面不好。其实,loadsh确实是一个很好的项目。以下例子只是一些可以在工作中覆盖大多数简单例子的简易代码片段;嗯,通常我们并不需要太复杂的工具。

噢,是的,以下所有代码都遵循不可变原则。我们不会去改变原始对象,而是返回一个有你想要的新对象。

希望它能帮助到你!

数组去重

在这里使用的方法是用我们的数据新建一个Set对象,然后把它转换成数组(假如需要的话):

1
2
3
4
// 返回去重后的数组
const numbers = [1, 2, 1, 1, 2, 1, 3, 4, 1 ];
const uniq = [...new Set(numbers)] // => [ 1, 2, 3, 4 ];
const uniq2 = Array.from(new Set(numbers)) // => [ 1, 2, 3, 4 ];

uniq和uniq2两种方法都可以转换成统一的数组。

  • javascript黑魔法:使用Set对象和扩展运算符 – @aurel_herve

在转换成数组之前,记得Set对象本身也有很多有用的方法哦,比如Size或者has。

根据属性来更新一个数组中的对象

接下来我们要更新数组中id:3的对象

1
2
3
4
5
// 更新数组中对象的属性
const initial = [ {id: 1, score: 1}, {id: 2, score: 2}, {id: 3, score: 4}];
const newValue = {id: 3, score: 3};
const updated = initial.map(x => x.id === newValue.id ? newValue : x);
console.log(updated) // => [ { id: 1, score: 1 }, { id: 2, score: 2 }, { id: 3, score: 3 } ]

当然,“原始”常量是保持不变的。

根据属性删除数组中的一个对象

让我们根据id === 3来删除数组中的那个对象。

1
2
3
4
// 根据属性删除数组中的对象
const removeId = 3;
const without3 = initial.filter(x => x.id !== removeId);
console.log(without3) // => [ { id: 1, score: 1 }, { id: 2, score: 2 } ]

当然,原始值还是保持不变。

删除一个对象上的属性(key)

你可以另辟蹊径:

//译者自己理解的(原文并没给出代码)

1
2
3
const obj = {a: 1, b: 2, c: 3};
const {a, ...newObj} = obj;
console.log(newObj) // => {b: 2, c: 3};

  • ES6黑魔法: 使用扩展运算符来删除一个对象上的属性(key) – @aurel_herve

合并数组中的对象

下面的代码中,我们既可以合并对象,也可以根据它们的属性来更新数组项。

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
// merge an array of objects
const data = [ {a: 1}, {b: 2}, {c: 3} ];
const merged = data.reduce((res, obj) => ({...res, ...obj}), {});
console.log(merged) // => { a: 1, b: 2, c: 3 }
// merge an array of objects by property
const toMerge = [
{ id: 1, value: 'a', },
{ id: 2, value: 'b', },
{ id: 3, value: 'c' },
{ id: 1, score: 1 },
{ id: 2, score: '2' },
]
const mergedByProperty = toMerge.reduce((result, obj) => ({
...result,
[obj.id]: {
...result[obj.id],
...obj
}
}), {})
console.log(mergedByProperty) // =>
/*
*{ '1': { id: 1, value: 'a', score: 1 },
* '2': { id: 2, value: 'b', score: '2' },
* '3': { id: 3, value: 'c' } }
*/

reduce和扩展运算符一起使用爽爆了吧。

  • 黑魔法之日: 合并两个数组中的对象,使用ES6扩展运算符。 – @aurel_herve
  • javascript黑魔法: 使用reduce和扩展运算符来合并对象 – @aurel_herve

扁平化(Flatten)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// 将一个二维数组转换成一个一维数组
const arrayOfArray = [ [1, 2], [3, 4], [[5, 6]] ];
const flattened = arrayOfArray.reduce((res, a) => [...res, ...a], [] );
console.log(flattened) // => [1, 2, 3, 4, [5, 6]];
数组的升级版扁平化
让我们继续javascript黑魔法: 一行代码搞定数组扁平化 -- @aurel_herve
成对扁平化(FromPairs)
// fromPairs
const pairs = [['a', 1], ['b', 2], ['c', 3]];
const asObjects = pairs
.reduce((res, [key, value]) => ({ ...res, [key]: value }), {});
// Or event smarter (thanks to @nomaed for pointing this one out)
const asObjects2 = { ...(new Map(pairs)) };
console.log(asObjects) // => { a: 1, b: 2, c: 3 };

我更喜欢[key, value]这样的数据结构 :)

  • 另一个有用的ES6单行魔法:成对的创建对象 – @aurel_herve

##两个Set对象相减

1
2
3
4
5
6
// subtract two sets
const s1 = [ 1, 2, 3, 4, 5 ];
const s2 = [ 2, 4 ];
const subtracted = s1.filter(x => s2.indexOf(x) < 0);
console.log(subtracted);
很少见但是很有用

结论

好的,这就是全部了。不要犹豫,可以告诉我更多的例子,或者你认为某些我忘记了但是常用的算法也可以告诉我!

我会持续更新哦 :)