等效于 C # LINQ Select 的 Javascript

下面是这个问题:

使用带有复选框列表的敲除选中绑定检查所有复选框

我使用淘汰创建了一些复选框,允许从数组中进行选择。 从上面的岗位上取下的工作提琴:

Http://jsfiddle.net/nscxj/

有没有一种简单的方法来创建一个只包含水果 ID 的数组?

我对 C # 更熟悉,我会做一些类似于 selectedFruits.select(fruit=>fruit.id);的事情

是否有一些方法/现成的函数可以用来做类似于 javascript/jquery 的事情?或者最简单的选择是循环遍历列表并创建第二个数组? 我打算用 JSON 将数组发送回服务器,因此我试图尽量减少发送的数据。

148389 次浏览

是的,Array.map ()$. map ()做同样的事情。

//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);

Http://jsfiddle.net/nscxj/1/

由于旧版本的浏览器不支持 array.map,我建议您坚持使用 jQuery 方法。

如果出于某种原因你更喜欢另一个,你可以添加一个旧的浏览器支持填充。

您也可以随时向数组原型添加自定义方法:

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;
});

一个扩展版本,如果你传递一个字符串,它会使用函数构造函数:

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'));

Http://jsfiddle.net/al85j/

更新:

因为这已经成为一个流行的答案,我增加了类似的我的 where() + firstOrDefault()。这些也可以与基于字符串的函数构造函数方法一起使用(这是最快的方法) ,但是这里有另一种使用对象文字作为过滤器的方法:

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 测试,用于比较函数构造函数和对象文本速度。如果决定使用前者,请记住正确引用字符串。

我个人的偏好是在过滤1-2个属性时使用基于对象文本的解决方案,并为更复杂的过滤传递一个回调函数。

在向本机对象原型添加方法时,我将以两个常规提示结束本文:

  1. 在覆盖前检查现有方法是否已经出现,例如:

    如果(! Array.Prototype.where){ 原型。

  2. 如果不需要支持 IE8及以下版本,可以使用 Object.defeProperty定义方法,使其不可枚举。如果有人在数组上使用 for..in(这是错误的) 它们也会迭代可枚举的属性,提醒一下。

看一下 下划线 js,它提供了许多类似 linq 的函数。在您给出的示例中,您将使用 map 函数。

因为使用了淘汰,所以应该考虑使用淘汰实用程序函数 arrayMap()和它的其他数组实用程序函数。

下面是数组实用函数及其等效 LINQ 方法的列表:

arrayFilter() -> Where()
arrayFirst() -> First()
arrayForEach() -> (no direct equivalent)
arrayGetDistictValues() -> Distinct()
arrayIndexOf() -> IndexOf()
arrayMap() -> Select()
arrayPushAll() -> (no direct equivalent)
arrayRemoveItem() -> (no direct equivalent)
compareArrays() -> (no direct equivalent)

所以你可以这样做:

var mapped = ko.utils.arrayMap(selectedFruits, function (fruit) {
return fruit.id;
});

如果您想在 javascript 中使用类似于 LINQ 的接口,您可以使用类似 Linq.js的库,它为许多 LINQ 方法提供了一个很好的接口。

var mapped = Enumerable.from(selectedFruits)
.select("$.id") // shorthand for `x => x.id`
.toArray();

我在 Tslinq.codeplex.com下为 TypeScript 构建了一个 Linq 库,你也可以用它来构建普通的 javascript。该库比 Linq.js 快2-3倍,并且包含所有 Linq 方法的单元测试。也许你可以回顾一下。

我知道这是一个迟到的回答,但它对我很有用!完成后,使用 $.grep函数可以模拟 linqwhere()

林克:

var maleNames = people
.Where(p => p.Sex == "M")
.Select(p => p.Name)

Javascript:

// replace where  with $.grep
//         select with $.map
var maleNames = $.grep(people, function (p) { return p.Sex == 'M'; })
.map(function (p) { return p.Name; });

你也可以试试 强 > linq.js

强 > linq.js你的

selectedFruits.select(fruit=>fruit.id);

将会是

Enumerable.From(selectedFruits).Select(function (fruit) { return fruit.id;  });

ES6的方式:

let people = [{firstName:'Alice',lastName:'Cooper'},{firstName:'Bob',age:'Dylan'}];
let names = Array.from(people, p => p.firstName);
for (let name of names) {
console.log(name);
}

也在: https://jsfiddle.net/52dpucey/

最相似的 C # Select类似物是 map函数。 使用:

var ids = selectedFruits.map(fruit => fruit.id);

selectedFruits数组中选择所有 id。

它不需要任何外部依赖,只需要纯 JavaScript