问题描述
在这里回答这个问题:
我使用淘汰赛创建了一些复选框,允许从数组中进行选择.从上面的帖子中提取的工作小提琴:
I've created some checkboxes using knockout that allow selection from an array.working fiddle taken from above post:
是否有一种简单的方法可以创建一个仅包含水果 ID 的数组?
Is there a simple way of creating an array of just the fruit's ID's?
我更喜欢使用 C#,在那里我会按照 selectedFruits.select(fruit=>fruit.id);
I'm more at home with C# where I would do something along the lines of selectedFruits.select(fruit=>fruit.id);
是否有一些方法/现成的函数可以与 javascript/jquery 做类似的事情?或者最简单的选择是遍历列表并创建第二个数组?我打算将数组以 JSON 格式发送回服务器,因此我试图尽量减少发送的数据.
Is there some method/ready made function for doing something similar with javascript/jquery? Or would the simplest option be to loop through the list and create a second array?I intend to post the array back to the server in JSON so am trying to minimize the data sent.
推荐答案
是的,Array.map() 或 $.map() 做同样的事情.
Yes, Array.map() or $.map() does the same thing.
//array.map:
var ids = this.fruits.map(function(v){
return v.Id;
});
//jQuery.map:
var ids2 = $.map(this.fruits, function (v){
return v.Id;
});
console.log(ids, ids2);
由于旧版浏览器不支持 array.map,我建议您坚持使用 jQuery 方法.
Since array.map isn't supported in older browsers, I suggest that you stick with the jQuery method.
如果你出于某种原因更喜欢另一个,你总是可以添加一个 polyfill 来支持旧的浏览器.
If you prefer the other one for some reason you could always add a polyfill for old browser support.
您也可以随时向数组原型添加自定义方法:
You can always add custom methods to the array prototype as well:
Array.prototype.select = function(expr){
var arr = this;
//do custom stuff
return arr.map(expr); //or $.map(expr);
};
var ids = this.fruits.select(function(v){
return v.Id;
});
如果您传递一个字符串,则使用函数构造函数的扩展版本.也许可以玩玩:
An extended version that uses the function constructor if you pass a string. Something to play around with perhaps:
Array.prototype.select = function(expr){
var arr = this;
switch(typeof expr){
case 'function':
return $.map(arr, expr);
break;
case 'string':
try{
var func = new Function(expr.split('.')[0],
'return ' + expr + ';');
return $.map(arr, func);
}catch(e){
return null;
}
break;
default:
throw new ReferenceError('expr not defined or not supported');
break;
}
};
console.log(fruits.select('x.Id'));
更新:
由于这已成为如此受欢迎的答案,因此我添加了类似的 where()
+ firstOrDefault()
.这些也可以与基于字符串的函数构造函数方法一起使用(这是最快的),但这是另一种使用对象文字作为过滤器的方法:
Since this has become such a popular answer, I'm adding similar my where()
+ firstOrDefault()
. These could also be used with the string based function constructor approach (which is the fastest), but here is another approach using an object literal as filter:
Array.prototype.where = function (filter) {
var collection = this;
switch(typeof filter) {
case 'function':
return $.grep(collection, filter);
case 'object':
for(var property in filter) {
if(!filter.hasOwnProperty(property))
continue; // ignore inherited properties
collection = $.grep(collection, function (item) {
return item[property] === filter[property];
});
}
return collection.slice(0); // copy the array
// (in case of empty object filter)
default:
throw new TypeError('func must be either a' +
'function or an object of properties and values to filter by');
}
};
Array.prototype.firstOrDefault = function(func){
return this.where(func)[0] || null;
};
用法:
var persons = [{ name: 'foo', age: 1 }, { name: 'bar', age: 2 }];
// returns an array with one element:
var result1 = persons.where({ age: 1, name: 'foo' });
// returns the first matching item in the array, or null if no match
var result2 = persons.firstOrDefault({ age: 1, name: 'foo' });
这是一个 jsperf 测试,用于比较函数构造函数与对象字面量的速度.如果您决定使用前者,请记住正确引用字符串.
Here is a jsperf test to compare the function constructor vs object literal speed. If you decide to use the former, keep in mind to quote strings correctly.
我个人的偏好是在过滤 1-2 个属性时使用基于对象字面量的解决方案,并通过回调函数进行更复杂的过滤.
My personal preference is to use the object literal based solutions when filtering 1-2 properties, and pass a callback function for more complex filtering.
在向本机对象原型添加方法时,我将用 2 个一般提示结束本文:
I'll end this with 2 general tips when adding methods to native object prototypes:
在覆盖之前检查现有方法的出现,例如:
Check for occurrence of existing methods before overwriting e.g.:
if(!Array.prototype.where) {Array.prototype.where = ...
如果您不需要支持 IE8 及以下,请使用 Object.defineProperty 使它们不可枚举.如果有人在数组上使用了 for..in
(这首先是错误的)他们也会迭代可枚举的属性.提个醒.
If you don't need to support IE8 and below, define the methods using Object.defineProperty to make them non-enumerable. If someone used for..in
on an array (which is wrong in the first place)they will iterate enumerable properties as well. Just a heads up.
这篇关于Javascript 等效于 C# LINQ Select的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!