首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >相当于C# LINQ Select的Javascript

相当于C# LINQ Select的Javascript
EN

Stack Overflow用户
提问于 2013-09-22 03:34:48
回答 14查看 129.7K关注 0票数 157

下面是这个问题:

Using the checked binding in knockout with a list of checkboxes checks all the checkboxes

我使用knockout创建了一些复选框,允许从数组中进行选择。工作小提琴取自上述帖子:

http://jsfiddle.net/NsCXJ/

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

我更熟悉C#,在那里我会按照selectedFruits.select(fruit=>fruit.id);的思路做一些事情

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

EN

回答 14

Stack Overflow用户

回答已采纳

发布于 2013-09-22 03:37:41

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

代码语言:javascript
复制
//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方法。

如果出于某些原因,您更喜欢另一个,您可以随时为旧浏览器支持添加polyfill。

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

代码语言:javascript
复制
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;
});

传递字符串时使用函数构造函数的扩展版本。一些可以玩玩的东西:

代码语言:javascript
复制
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()。这些也可以用于基于字符串的函数构造方法(这是最快的),但这里是另一种使用对象文字作为过滤器的方法:

代码语言:javascript
复制
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;
};

用法:

代码语言:javascript
复制
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 test。如果您决定使用前者,请记住正确地引用字符串。

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

在将方法添加到原生对象原型时,我将用两个一般技巧来结束这一点:

  1. 在覆盖之前检查现有方法的出现情况,例如:

if(!Array.prototype.where) { Array.prototype.where = ...

  • If您不需要支持IE8或更低版本,请使用Object.defineProperty定义方法,使其不可枚举。如果有人在数组上使用了for..in (这首先是错误的),他们也会迭代可枚举的属性。只是提醒一下。
票数 250
EN

Stack Overflow用户

发布于 2014-05-15 22:35:11

我知道这是一个迟来的答案,但它对我很有用!最后,使用$.grep函数可以模拟linq where()

Linq:

代码语言:javascript
复制
var maleNames = people
.Where(p => p.Sex == "M")
.Select(p => p.Name)

Javascript:

代码语言:javascript
复制
// replace where  with $.grep
//         select with $.map
var maleNames = $.grep(people, function (p) { return p.Sex == 'M'; })
            .map(function (p) { return p.Name; });
票数 33
EN

Stack Overflow用户

发布于 2013-09-22 06:12:10

由于您正在使用knockout,因此应该考虑使用knockout实用函数arrayMap()和它的其他数组实用函数。

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

代码语言:javascript
复制
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)

因此,您可以在您的示例中执行以下操作:

代码语言:javascript
复制
var mapped = ko.utils.arrayMap(selectedFruits, function (fruit) {
    return fruit.id;
});

如果你想在javascript中有一个类似LINQ的接口,你可以使用像linq.js这样的库,它为许多LINQ方法提供了一个很好的接口。

代码语言:javascript
复制
var mapped = Enumerable.from(selectedFruits)
    .select("$.id") // shorthand for `x => x.id`
    .toArray();
票数 17
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/18936774

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档