學習 選擇set 而不是array 以及 多個箭頭函數

近日在學習如何簡化代碼時,看見一道google面試題

題目:

對函數傳入一個數組和sum, 函數需要判斷 任兩個數字加起來是否等於sum,如果有返回true,都沒有則返回false

思路

在遍歷之前聲明一個遍量(searchValues ),用來儲存所有需要匹配的數字差。
接著首遍歷每一個數組元素,在計算出該數字需要和哪個數字配對即可等於sum,將該數字差值儲存在searchVal裡 ,用來之後判斷目前的searchValues 中是否存在該值,如果有則返回true 退出循環,如果沒有則將此次計算的差值存入searchValues 以便下數字繼續判斷。

const findSum = (arr, val) => {
  let searchValues = new Set();
  searchValues.add(val - arr[0]);
  for (let i = 1, length = arr.length; i < length; i++) {
    let searchVal = val - arr[i];
    if (searchValues.has(arr[i])) {
      return true;
    } else {
      searchValues.add(searchVal);
    }
  };
  return false;
};
優化

首先此次的邏輯是只要有 ’ 一個 ’ 符合需求即可返回true, 那麼首先想到的應該就是 some 方法。

const findSum = (arr, sum) =>
  arr.some((set => n => set.has(n) || !set.add(sum - n))(new Set));
1. 性能選擇

上面的方法比起常見的array,使用的是我平常不常見的set方法,上網學習一般後發現兩者最顯著的方法是 index array靠著索引來判斷不同元素,而set則無。為了驗證方法,可以實際來測試這兩個方法在自己電腦上運行的時間

a 用array和set各創建元素:

首先我們用array和set方法各插入 0~1000000的元素

let arr = [], set = new Set(), n = 1000000;
for (let i = 0; i < n; i++) {
  arr.push(i);
  set.add(i);
}
b 查找元素

接著來測試 兩個方法查找元素各別的時間
結果會發現 set 確實比array快了整整5倍


 
let result;
console.time('Array'); 
result = arr.indexOf(123123) !== -1; 
console.timeEnd('Array');
console.time('Set'); 
result = set.has(123123); 
console.timeEnd('Set');
// Array: 0.151123046875 ms
// Set: 0.002685546875 ms
c 添加元素

再添加方面 set 比array快了1.5倍

console.time('Array'); 
arr.push(n);
console.timeEnd('Array');
console.time('Set'); 
set.add(n);
console.timeEnd('Set');
// Array: 0.003173828125 ms
// Set: 0.002197265625 ms
d. 刪除元素

使先創建個輔助函數用來測試

 
const deleteFromArr = (arr, item) => {
  let index = arr.indexOf(item);
  return index !== -1 && arr.splice(index, 1);
};

測試代碼:
再刪除方面 set 比array快了400多倍

console.time('Array'); 
deleteFromArr(arr, n);
console.timeEnd('Array');
console.time('Set'); 
set.delete(n);
console.timeEnd('Set');
// Array: 1.5791015625 ms
// Set: 0.003662109375 ms

柯理化函數

回到優化的代碼中,我們已經了解了為何使用set的原因,接下來讓人疑惑的地方又來了,有兩個箭頭函數???我們知道some裡的參數是代表被遍歷的各個元素,但是兩組參數及箭頭函數又代表什麼呢?

const findSum = (arr, sum) =>
  arr.some((set => n => set.has(n) || !set.add(sum - n))(new Set));

在stackflow上的答案就是 柯理函數 curried function
在这里插入图片描述

原參考網址 https://stackoverflow.com/questions/32782922/what-do-multiple-arrow-functions-mean-in-javascript

簡單來說 柯理函數可以形成惰性傳值,我們注意到最尾端傳入了new Set()方法進去some方法中,這裡代表的就是new Set 在some中形成了閉包

// 原本的函數
let add = (x, y) => x + y
let add2 = add(2,3)
// 柯理函數
let add = x => y => x + y
let add2 =add(2)(3)

也就是說在沒有使用柯理函數的情況下,它會是

const add = function (x) {
  return function (y) {
    return x + y
  }
}

更多相關可以參考 stackoverflowjs 中的多个连续的箭头函数与柯里化

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值