下劃線提供對函數sortBy
進行排序的對象數組。但是,一旦我有這個排序的數組,是否有一種方法來使用二分查找找到一個元素?函數find
不利用數組已排序的事實,而函數indexOf
具有排序功能,但它不提供指定排序關鍵字的方法。下劃線 - 從排序的對象數組中查找
- 我錯過了什麼嗎?
- 有沒有其他的JS庫可以輕鬆地做到這一點?
下劃線提供對函數sortBy
進行排序的對象數組。但是,一旦我有這個排序的數組,是否有一種方法來使用二分查找找到一個元素?函數find
不利用數組已排序的事實,而函數indexOf
具有排序功能,但它不提供指定排序關鍵字的方法。下劃線 - 從排序的對象數組中查找
功能_.sortedIndex
用於二分查找,但比您的目的更通用一些。我只想用它來建立一個sortedFind,例如:
_.sortedFind = function sortedFind(list, item, key) {
return (_.isEqual(item, list[_.sortedIndex(list, item, key)]));
}
實例應用:
// http://jsfiddle.net/w3hzrehy/
_.sortedFind([10, 20, 30, 40, 50], 10); // true
var stooges = [{name: 'moe', age: 40}, {name: 'curly', age: 60}];
_.sortedFind(stooges, {name: 'larry', age: 50}, 'age'); // false
_.sortedFind(stooges, {name: 'curly', age: 60}, 'age'); // true
謝謝。這非常接近!我其實想找到給定值的索引。所以'_.sortedFind(stooges,{name:'curly'},'name');'應該返回索引1.我相信'_.sortedIndex(stooges,{name:'curly'},'name');儘管我沒有發送完整的內容,但確實如此。我需要做的是檢查返回的索引是否確實包含名稱爲'curly'的項目。下劃線文檔對此並不十分清楚,但我認爲這是它應該如何工作的。你能確認嗎? – Naresh 2014-09-22 01:32:41
這裏是我想要的jsfiddle:http://jsfiddle.net/w3hzrehy/16/ – Naresh 2014-09-22 01:59:13
@Naresh是的,它看起來像你正在使用'sortedIndex',如果你要重用你的功能,你可能想概括它基於函數和純價值排序:http://jsfiddle.net/w3hzrehy/18/(注意我必須升級下劃線才能訪問_iteratee()函數。) – lossleader 2014-09-22 11:43:33
你是不是缺少什麼。這有點令人驚訝,不是嗎?
谷歌封庫做的binarySearch的內部支持功能(我敢肯定有其他人):
http://docs.closure-library.googlecode.com/git/namespace_goog_array.html
你會使用它,就像你想象:
var myArray = getPetArray();
goog.array.binarySearch(myArray, 'fido', function(pet) { return pet.name; });
如果您不想拖入另一個圖書館,則該來源很短並且可用:
http://docs.closure-library.googlecode.com/git/local_closure_goog_array_array.js.source.html#line989
我砍在這裏的情況下粘貼重要組成部分,鏈接改變 - 只是要記住將給予信貸谷歌:
goog.array.binarySearch = function(arr, target, opt_compareFn) {
return goog.array.binarySearch_(arr,
opt_compareFn || goog.array.defaultCompare, false /* isEvaluator */,
target);
};
goog.array.binarySearch_ = function(arr, compareFn, isEvaluator, opt_target,
opt_selfObj) {
var left = 0; // inclusive
var right = arr.length; // exclusive
var found;
while (left < right) {
var middle = (left + right) >> 1;
var compareResult;
if (isEvaluator) {
compareResult = compareFn.call(opt_selfObj, arr[middle], middle, arr);
} else {
compareResult = compareFn(opt_target, arr[middle]);
}
if (compareResult > 0) {
left = middle + 1;
} else {
right = middle;
// We are looking for the lowest index so we can't return immediately.
found = !compareResult;
}
}
// left is the index if found, or the insertion point otherwise.
// ~left is a shorthand for -left - 1.
return found ? left : ~left;
};
goog.array.defaultCompare = function(a, b) {
return a > b ? 1 : a < b ? -1 : 0;
};
謝謝,這是一個很好的解決方案。然而,@ lossleader的解決方案可以用很少的額外努力使用下劃線實現,因此我將其標記爲接受的答案。再次感謝你的幫助。 – Naresh 2014-09-22 01:39:32
好奇:你在做什麼,一個二進制搜索使得聽話的和不可接受的區別?你的陣列有多大?你在做什麼? – 2014-09-21 21:06:22
二進制搜索必須在已排序的數組上執行。既然你有一個對象數組,你很可能需要一個自定義的解決方案。 – 2014-09-21 21:40:51
該陣列本身約有1000個物品,但我需要多次查找物品。所以在循環中對這個數組進行線性搜索可能不是很有效。 – Naresh 2014-09-22 01:35:34