假设我有一个<select>
元素:
<select id="foobar" name="foobar" multiple="multiple">
<option value="1">Foobar 1</option>
<option value="2">Foobar 2</option>
<option value="3">Foobar 3</option>
</select>
让我们假设我有一系列值,例如:
var optionValues = [2, 3];
如何最有效地选择值为2和3的<option>
?
我正在使用拥有数千<select>
个<option>
的{{1}},因此这样做手动无效:
var optionElements = [];
$("#foobar").children().each(function() {
if($.inArray($(this).val(), optionValues)) {
optionElements.push($(this));
}
}
这太慢了。有没有办法将jQuery的值列表交给我需要选择的元素?有什么想法吗?
P.S。如果您想知道,我正在优化目前jQuery PickList widget的sucks at handling large lists。
答案 0 :(得分:3)
您是否考虑过在插件引导程序中创建一个大哈希表?授予的值是唯一的:
var options = {};
$('#foobar').children().each(function(){
options[this.value] = this;
});
这种查找方式很简单 - options[valueNeeded]
。
编辑 - 搜索optionValues
:
var optionValues = [2, 3];
var results = [];
for(i=0; i<optionValues.length;i++){
results.push[ options[ optionValues[i] ] ];
}
答案 1 :(得分:2)
这还没有被描述过,所以用一个 grain 盐的振动器拿它:
var options = $("some-select").children(),
toFind = [2, 3],
values = {},
selectedValues = [],
unSelectedValues = [];
// First, make a lookup table of selectable values
// O(1) beats O(n) any day
for (i=0, l=toFind.length; i++; i<l) {
values[toFind[i]] = true;
}
// Avoid using more complicated constructs like `forEach` where speed is critical
for (i=0, l=options.length; i++; i<l) {
// Avoid nasty edge cases since we need to support *all* possible values
// See: http://www.devthought.com/2012/01/18/an-object-is-not-a-hash/
if (values[options[i]] === true) {
selectedValues.push(options[i]);
}
else {
unSelectedValues.push(options[i]);
}
}
我们显然可以做更多事情(比如缓存选定和未选中的值,以便我们可以避免每次用户在它们之间移动值时重建它们)如果我们假设数据都是唯一的,我们甚至可以将整个三分之二&#34;哈希&#34; - 但无论我们做什么we should profile it和确保它确实和我们认为一样快。
答案 2 :(得分:1)
假设值是唯一的,您可以采取一些快捷方式。例如,一旦找到了值,就可以通过splice()
将其从搜索数组中删除来停止搜索。
这将是最终的优化,将您从O(n^2)
一直带到O(n log n)
:排序。
首先,遍历选项并构建一个数组。基本上你只想将NodeList转换为数组。然后,sort
数组带有回调以获取选项的值。对搜索数组进行排序。现在,您可以遍历“options”数组并查找当前最小的搜索项。
var optsNodeList = document.getElementById('foobar').options,
optsArray = [], l = optsNodeList.length, i,
searchArray = [2,3], matches = [], misses = [];
for( i=0; i<l; i++) optsArray[i] = optsNodeList[i];
optsArray.sort(function(a,b) {return a.value < b.value ? -1 : 1;});
searchArray.sort();
while(searchArray[0] && (i = optsArray.shift())) {
while( i > searchArray[0]) {
misses.push(searchArray.shift());
}
if( i == searchArray[0]) {
matches.push(i);
searchArray.shift();
}
}
答案 3 :(得分:1)
试试这个:
var $found = [];
var notFound = [];
var $opt = $('#foobar option');
$.each(optionValues, function(i, v){
var $this = $opt.filter('[value='+v+']');
if ($this.length) {
$elems.push($this)
} else {
notFound.push(v);
}
})
答案 4 :(得分:1)
首先,我要感谢大家的精彩回应!我正在考虑每个人,在做出决定之前我可能会做基准测试。
在此期间,我实际上找到了另一个问题的“可接受的”解决方案based on this answer。
这就是我提出的(最后一个块,使用自定义filter()
实现,是神奇发生的地方):
var items = self.sourceList.children(".ui-selected");
var itemIds = [];
items.each(function()
{
itemIds.push( this.value );
});
self.element.children().filter(function()
{
return $.inArray(this.value, itemIds) != -1;
}).attr("selected", "selected");
我怀疑这个效果和你们发布的任何内容一样有效,但是它在1500项目列表中将“添加”选项列表操作时间从大约10秒减少到300毫秒。
答案 5 :(得分:1)
我会尝试jQuery的filter()
方法,例如:
var matches = filter(function() {
// Determine if "this" is a match and return true/false appropriately
});
// Do something with the matches
matches.addClass('foobar');
这可能不是最快的解决方案,但它相当优化,非常简单,无需跟踪列表和所有爵士乐。它应该足够快你的情况。
答案 6 :(得分:0)
试试这个。
var optionValues = [2, 3],
elements = [],
options = document.getElementById('foobar').options;
var i = 0;
do {
var option = options[i];
if(optionValues.indexOf(+option.value) != -1) {
elements.push(option);
}
} while(i++ < options.length - 1);
答案 7 :(得分:0)
让optionValues由一组索引选择。
for(var i = 0; i < optionValues.length; i++) {
document.forms[0].foobar.options[optionValues[i]].selected = true;
}
答案 8 :(得分:0)
如果您只想按值选择,则以下内容应该合适。它只循环选项一次,不调用任何其他函数,只调用一个内置方法,因此它应该很快。
function selectMultiByValue(el, valuesArr) {
var opts = el.options;
var re = new RegExp('^(' + valuesArr.join('|') + ')$');
// Select options
for (var i=0, iLen=opts.length; i<iLen; i++) {
opts[i].selected = re.test(opts[i].value);
}
}
在某些浏览器中,循环遍历集合很慢,因此首先将选项集合转换为数组可能需要付费。但在测试之前测试可能不值得。
请注意,如果select不是多选,则只会选择带有最后列出值的选项。
如果您想允许其他各种字符或案例,您可能需要摆弄正则表达式。