學underscore在陣列中查詢指定元素

2022-09-16 03:24:09 字數 4769 閱讀 8657

在開發中,我們經常會遇到在陣列中查詢指定元素的需求,可能大家覺得這個需求過於簡單,然而如何優雅的去實現乙個 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 stooges

var 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...