在開發中,我們經常會遇到在陣列中查詢指定元素的需求,可能大家覺得這個需求過於簡單,然而如何優雅的去實現乙個 findindex 和 findlastindex、indexof 和 lastindexof 方法卻是很少人去思考的。本文就帶著大家一起參考著 underscore 去實現這些方法。
在實現前,先看看 es6 的 findindex 方法,讓大家了解 findindex 的使用方法。
es6 對陣列新增了 findindex 方法,它會返回陣列中滿足提供的函式的第乙個元素的索引,否則返回 -1。
舉個例子:
function isbigenough(element)[12, 5, 8, 130, 44].findindex(isbigenough); // 3
findindex 會找出第乙個大於 15 的元素的下標,所以最後返回 3。
是不是很簡單,其實,我們自己去實現乙個 findindex 也很簡單。
思路自然很明了,遍歷一遍,返回符合要求的值的下標即可。
function findindex(array, predicate, context)return -1;
}console.log(findindex([1, 2, 3, 4], function(item, i, array))) // 2
findindex 是正序查詢,但正如 indexof 還有乙個對應的 lastindexof 方法,我們也想寫乙個倒序查詢的 findlastindex 函式。實現自然也很簡單,只要修改下迴圈即可。
function findlastindex(array, predicate, context)return -1;
}console.log(findlastindex([1, 2, 3, 4], function(item, index, array))) // 0
然而問題在於,findindex 和 findlastindex 其實有很多重複的部分,如何精簡冗餘的內容呢?這便是我們要學習的地方,日後面試問到此類問題,也是加分的選項。
underscore 的思路就是利用傳參的不同,返回不同的函式。這個自然是簡單,但是如何根據引數的不同,在同乙個迴圈中,實現正序和倒序遍歷呢?
讓我們直接模仿 underscore 的實現:
function createindexfinder(dir)return -1;
}}var findindex = createindexfinder(1);
var findlastindex = createindexfinder(-1);
findindex 和 findlastindex 的需求算是結束了,但是又來了乙個新需求:在乙個排好序的陣列中找到 value 對應的位置,保證插入陣列後,依然保持有序的狀態。
假設該函式命名為 sortedindex,效果為:
sortedindex([10, 20, 30], 25); // 2
也就是說如果,注意是如果,25 按照此下標插入陣列後,陣列變成 [10, 20, 25, 30],陣列依然是有序的狀態。
那麼這個又該如何實現呢?
既然是有序的陣列,那我們就不需要遍歷,大可以使用二分查詢法,確定值的位置。讓我們嘗試著去寫一版:
// 第一版function sortedindex(array, obj)
return high;
};console.log(sortedindex([10, 20, 30, 40, 50], 35)) // 3
現在的方法雖然能用,但通用性不夠,比如我們希望能處理這樣的情況:
// stooges 配角 比如 三個臭皮匠 the three stoogesvar stooges = [, ];
var result = sortedindex(stooges, , function(stooge));
console.log(result) // 1
所以我們還需要再加上乙個引數 iteratee 函式對陣列的每乙個元素進行處理,一般這個時候,還會涉及到 this 指向的問題,所以我們再傳乙個 context 來讓我們可以指定 this,那麼這樣乙個函式又該如何寫呢?
// 第二版function cb(fn, context)
}function sortedindex(array, obj, iteratee, context)
return high;
};
sortedindex 也完成了,現在我們嘗試著去寫乙個 indexof 和 lastindexof 函式,學習 findindex 和 findlastindex 的方式,我們寫一版:
// 第一版function createindexoffinder(dir)
return -1;
}}var indexof = createindexoffinder(1);
var lastindexof = createindexoffinder(-1);
var result = indexof([1, 2, 3, 4, 5], 2);
console.log(result) // 1
但是即使是陣列的 indexof 方法也可以多傳遞乙個引數 fromindex,從 mdn 中看到 fromindex 的講究可有點多:
設定開始查詢的位置。如果該索引值大於或等於陣列長度,意味著不會在陣列裡查詢,返回 -1。如果引數中提供的索引值是乙個負值,則將其作為陣列末尾的乙個抵消,即 -1 表示從最後乙個元素開始查詢,-2 表示從倒數第二個元素開始查詢 ,以此類推。 注意:如果引數中提供的索引值是乙個負值,仍然從前向後查詢陣列。如果抵消後的索引值仍小於 0,則整個陣列都將會被查詢。其預設值為 0。再看看 lastindexof 的 fromindex:
從此位置開始逆向查詢。預設為陣列的長度減 1,即整個陣列都被查詢。如果該值大於或等於陣列的長度,則整個陣列會被查詢。如果為負值,將其視為從陣列末尾向前的偏移。即使該值為負,陣列仍然會被從後向前查詢。如果該值為負時,其絕對值大於陣列長度,則方法返回 -1,即陣列不會被查詢。按照這麼多的規則,我們嘗試著去寫第二版:
// 第二版function createindexoffinder(dir)
else
}for (idx = dir > 0 ? i : length - 1; idx >= 0 && idx < length; idx += dir)
return -1;
}}var indexof = createindexoffinder(1);
var lastindexof = createindexoffinder(-1);
到此為止,已經很接近原生的 indexof 函式了,但是 underscore 在此基礎上還做了兩點優化。
第乙個優化是支援查詢 nan。
因為 nan 不全等於 nan,所以原生的 indexof 並不能找出 nan 的下標。
[1, nan].indexof(nan) // -1
那麼我們該如何實現這個功能呢?
就是從陣列中找到符合條件的值的下標嘛,不就是我們最一開始寫的 findindex 嗎?
我們來寫一下:
// 第三版function createindexoffinder(dir, predicate)
// 判斷元素是否是 nan
if (item !== item)
for ()
}}var indexof = createindexoffinder(1, findindex);
var lastindexof = createindexoffinder(-1, findlastindex);
第二個優化是支援對有序的陣列進行更快的二分查詢。
如果 indexof 第三個引數不傳開始搜尋的下標值,而是乙個布林值 true,就認為陣列是乙個排好序的陣列,這時候,就會採用更快的二分法進行查詢,這個時候,可以利用我們寫的 sortedindex 函式。
在這裡直接給最終的原始碼:
// 第四版function createindexoffinder(dir, predicate, sortedindex)
else
}else if (sortedindex && idx && length)
// 判斷是否是 nan
if (item !== item)
for (idx = dir > 0 ? i : length - 1; idx >= 0 && idx < length; idx += dir)
return -1;
}}var indexof = createindexoffinder(1, findindex, sortedindex);
var lastindexof = createindexoffinder(-1, findlastindex);
值得注意的是:在 underscore 的實現中,只有 indexof 是支援有序陣列使用二分查詢,lastindexof 並不支援。
跟著underscore學防抖
在前端開發中會遇到一些頻繁的事件觸發,比如 window 的 resize scroll mousedown mousemove keyup keydown 為此,我們舉個示例 來了解事件如何頻繁的觸發 我們寫個index.html檔案 debouncetitle container style h...
陣列 在陣列中查詢元素
description 輸入10個整數到乙個長度為10的整型陣列中,然後輸入乙個整數,檢視該整數是否在剛才得到的陣列中,如果在,輸出 found 如果不在,輸出 not found input 11 個整數 output 如果第11個整數在前10個整數中,則輸出found 如果第11個整數不在前10...
在陣列中查詢數字
在整型有序陣列中查詢想要的數字,查到了返回下標 折半查詢 define crt secure no warnings include include intmain int num scanf d num int left 0 int right 10 while left right else i...