fork 了一份代码来看: 4ker/30-seconds-of-code: Curated collection of useful Javascript snippets that you can understand in 30 seconds or less., 分享点看到的比较有意思的地方.
filter 的使用
// a\b
const difference = (a, b) => { const s = new Set(b); return a.filter(x => !s.has(x)); };
// a∩b
const intersection = (a, b) => { const s = new Set(b); return a.filter(x => s.has(x)); };
// a∪b
const union = (a, b) => Array.from(new Set([...a, ...b]));
// compact 就是去掉 falsy 的元素
const compact = (arr) => arr.filter(v => v);
// unique 就是 indexOf 和 lastIndexOf 一样的元素
const filterNonUnique = arr => arr.filter(i => arr.indexOf(i) === arr.lastIndexOf(i));
妙用随机数
// 取元素
const sample = arr => arr[Math.floor(Math.random() * arr.length)];
// 打乱元素
const shuffle = arr => arr.sort(() => Math.random() - 0.5);
注:上面的 shuffle 写起来方便,但排序后元素的预期分布不均匀,详细见 10809 一种错误的洗牌算法,以及乱排常数 (1)。
reduce 的使用
// reduce 出一个数值
const countOccurrences = (arr, value) => arr.reduce((a, v) => v === value ? a + 1 : a + 0, 0);
// reduce 出一个 list
const fibonacci = n =>
Array(n).fill(0).reduce((acc, val, i) => acc.concat(i > 1 ? acc[i - 1] + acc[i - 2] : i), []);
// reduce 出一个 object
const objectFromPairs = arr => arr.reduce((a, v) => (a[v[0]] = v[1], a), {});
// 利用 reduce 的第三个参数 index
const groupBy = (arr, func) =>
arr.map(typeof func === 'function' ? func : val => val[func])
.reduce((acc, val, i) => { acc[val] = (acc[val] || []).concat(arr[i]); return acc; }, {});
// key in obj, 还用了 (exp1, exp2, ..., expN) 返回值为 expN
const pick = (obj, arr) =>
arr.reduce((acc, curr) => (curr in obj && (acc[curr] = obj[curr]), acc), {});
// 如果 reduce 没有第二个参数, 会从第 1,2 个开始 reduce: arr.reduce(callback[, initialValue])
const pipe = (...fns) => fns.reduce((f, g) => (...args) => g(f(...args)));
/*
const add5 = x => x + 5
const multiply = (x, y) => x * y
const multiplyAndAdd5 = pipe(multiply, add5)
multiplyAndAdd5(5, 2) -> 15
*/
递归
// 拍扁, concat 如果接收到一个 obj, 就 push, 如果是一个 list, 就合并
const flatten = arr => arr.reduce((a, v) => a.concat(v), []);
// 有点好奇为啥要 [].concat(list) 而不直接用 list, 这是在获取拷贝?
const deepFlatten = arr => [].concat(...arr.map(v => Array.isArray(v) ? deepFlatten(v) : v));
// 如果要控制层数, 只能是多一个 flag, 然后每次递归的时候 check 一下
const flattenDepth = (arr, depth = 1) =>
depth != 1 ? arr.reduce((a, v) => a.concat(Array.isArray(v) ? flattenDepth(v, depth - 1) : v), [])
: arr.reduce((a, v) => a.concat(v), []);
// 尾递归不需要新开栈, 避免了爆栈, 通常加一个参数来存储
const factorial = n => n <= 1 ? 1 : n * factorial(n - 1);
const factorial = (n, ret=1) => n <= 1 ? ret : factorial(n - 1, n*ret);
MISC
// toString(2)
const hammingDistance = (num1, num2) =>
((num1 ^ num2).toString(2).match(/1/g) || '').length;
// "一遍一遍刷"
const powerset = arr =>
arr.reduce((a, v) => a.concat(a.map(r => r.concat(v))), [[]]);
// powerset([1,2]) -> [[], [1], [2], [1,2]]
// 获取 queries
const getUrlParameters = url =>
url.match(/([^?=&]+)(=([^&]*))/g).reduce(
(a, v) => (a[v.slice(0, v.indexOf('='))] = v.slice(v.indexOf('=') + 1), a), {}
);
// getUrlParameters('http://url.com/page?name=Adam&surname=Smith') -> {name: 'Adam', surname: 'Smith'}
网友评论