"30 seconds of code"中好玩的代码片段

最近做了github出现一个挺火的代码库"30 seconds of code",里面有不少好玩的代码片段,这里做一个分享,以下分享8个有趣的代码片段,有兴趣可以亲自点开看看

1、difference

Returns the difference between two arrays. Create a Set from b, then use Array.filter() on a to only keep values not contained in b.

const difference1 = (a, b) => { const s = new Set(b); return a.filter(x => !s.has(x)); };
// difference1([1,2,3], [1,2,4]) -> [3]
复制代码

王二还想出了如下两种解决方法,也可以满足以上需求:

const difference2 = (a, b) => { return a.filter( _ => !b.some(($)=>(_===$))};

const difference3 = (a, b) => { return a.filter( _ => !b.includes(_))};
复制代码
2、pick

Picks the key-value pairs corresponding to the given keys from an object. Use Array.reduce() to convert the filtered/picked keys back to a object with the corresponding key-value pair if the key exist in the obj.

const pick1 = (obj, arr) => arr.reduce((acc, curr) => (curr in obj && (acc[curr] = obj[curr]), acc), {});
// pick1({ 'a': 1, 'b': '2', 'c': 3 }, ['a', 'c']) -> { 'a': 1, 'c': 3 }
复制代码

如果不用reduce而使用一般的解决循环,也可以解决以上需求,例如王二如下给出的方法,不过用reduce一行就能搞定,当然是显得更优雅了。

const pick2 = (obj, arr) => {
    const res = {};
    arr.forEach(curr => (curr in obj && (res[curr] = obj[curr])));
    return res ;
};
复制代码
3、zip

Creates an array of elements, grouped based on the position in the original arrays.

Use Math.max.apply() to get the longest array in the arguments. Creates an array with that length as return value and use Array.from() with a map-function to create an array of grouped elements. If lengths of the argument-arrays vary, undefined is used where no value could be found.

const zip1 = (...arrays) => {
  const maxLength = Math.max(...arrays.map(x => x.length));
  return Array.from({length: maxLength}).map((_, i) => {
   return Array.from({length: arrays.length}, (_, k) => arrays[k][i]);
  })
}
//zip1(['a', 'b'], [1, 2], [true, false]); -> [['a', 1, true], ['b', 2, false]]
//zip1(['a'], [1, 2], [true, false]); -> [['a', 1, true], [undefined, 2, false]]
复制代码

以上需求一般的解决方法如下所示,可以用两层for循环搞定。但是很显然,上面的写法显得更优雅;

const zip2 = () => {
    var arr = Array.prototype.slice.call(arguments),
          maxLength = 0,
          out = [];
    arr.forEach(function(i){
        maxLength = Math.max(i.length,maxLength) ;
    })
    for(var x=0;x<maxLength;x++){
        var temp = [];
        for(var y=0;y<arr.length;y++){
            temp.push(arr[y][x]);
        }
        out.push(temp);
    }
    return out;
}
复制代码
4、getBoundingClientRect()

dom元素使用getBoundingClientRect()可以获得其详细的位置。

5、getURLParameters

Returns an object containing the parameters of the current URL.

Use match() with an appropriate regular expression to get all key-value pairs, Array.reduce() to map and combine them into a single object. Pass location.search as the argument to apply to the current url.


const getURLParameters1 = () =>
  location.href.match(/([^?=&]+)(=([^&]*))/g).reduce(
    (a, v) => (a[v.slice(0, v.indexOf('='))] = v.slice(v.indexOf('=') + 1), a), {}
  );
// location.href = 'http://url.com/page?name=Adam&surname=Smith';
// getURLParameters() -> {name: 'Adam', surname: 'Smith'}
复制代码

一般的解决思路如下,但是以上的方法用正则加reduce一行就能搞定;

const getURLParameters2 = () => {
    //取得查询字符串并去掉开头的问号
    var qs = (location.search.length > 0 ? location.search.substring(1) : ""),
    //保存数据的对象
    args = {},
    //取得每一项
    items = qs.length ? qs.split("&") : [],
    item = null,
    name = null, 
    value = null,
    //在 for 循环中使用
    i = 0,
    len = items.length;
    //逐个将每一项添加到 args 对象中
    for (i=0; i < len; i++){
        item = items[i].split("=");
        name = decodeURIComponent(item[0]);
        value = decodeURIComponent(item[1]);
        if (name.length) {
            args[name] = value;
        }
    }
    return args;
}
复制代码
6、curry

Curries a function.

Use recursion. If the number of provided arguments (args) is sufficient, call the passed function f. Otherwise return a curried function f that expects the rest of the arguments. If you want to curry a function that accepts a variable number of arguments (a variadic function, e.g. Math.min()), you can optionally pass the number of arguments to the second parameter arity.

const curry = (fn, arity = fn.length, ...args) =>
  arity <= args.length
    ? fn(...args)
    : curry.bind(null, fn, arity, ...args);
// curry1(Math.pow)(2)(10) -> 1024
// curry1(Math.min, 3)(10)(50)(2) -> 2
复制代码

一些王二一直弄不明白什么叫做柯里化,这个函数给王二好好上了一课;

7、pipe

Performs left-to-right function composition.

Use Array.reduce() with the spread operator (...) to perform left-to-right function composition. The first (leftmost) function can accept one or more arguments; the remaining functions must be unary.

const pipeFunctions = (...fns) => fns.reduce((f, g) => (...args) => g(f(...args)));
/*
const add5 = x => x + 5
const multiply = (x, y) => x * y
const multiplyAndAdd5 = pipeFunctions(multiply, add5)
multiplyAndAdd5(5, 2) -> 15
*/
复制代码

王二第一次看到这个函数简直就是黑科技;

8、fibonacci

Generates an array, containing the Fibonacci sequence, up until the nth term.

Create an empty array of the specific length, initializing the first two values (0 and 1). Use Array.reduce() to add values into the array, using the sum of the last two values, except for the first two.

const fibonacci = n =>
  Array.from({ length: n}).map(v => 0).reduce((acc, val, i) => acc.concat(i > 1 ? acc[i - 1] + acc[i - 2] : i), []);
// fibonacci(5) -> [0,1,1,2,3]
复制代码

一行函数搞定斐波那契数列。这里,王二觉得作者写的有些偏差,实际上,这里不需要map(v => 0),如下:

const fibonacci = n =>
  Array.from({ length: n}).reduce((acc, val, i) => acc.concat(i > 1 ? acc[i - 1] + acc[i - 2] : i), []);
// fibonacci(5) -> [0,1,1,2,3]
复制代码

当然,还有其他的解决方案,如下:

const fibonacci = n =>
  Array(n).fill(0).reduce((acc, val, i) => acc.concat(i > 1 ? acc[i - 1] + acc[i - 2] : i), []);
复制代码

一般的解决思路如下:

const fibonacci = n =>{
    var out = [];
    for(var i=0;i<n;i++){
        i > 1 ? out.push(out[i-1]+out[i-2]) : out.push(i);
    }
    return out ;
}
复制代码

小结:无聊时看两段,每段理解起来不过30秒,实在是居家旅行必备的良品!赶紧戳进来看看

原文章发表于:王玉略的个人网站

转载于:https://juejin.im/post/5a3caaabf265da4320036efb

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值