knockout.js 与C# LINQ Select等效的Javascript

lsmd5eda  于 2022-11-10  发布在  C#
关注(0)|答案(8)|浏览(184)

下面这个问题:
Using the checked binding in knockout with a list of checkboxes checks all the checkboxes
我已经创建了一些复选框使用敲除,允许从一个数组中选择。
http://jsfiddle.net/NsCXJ/
有没有一种简单的方法来创建一个只包含水果ID的数组?
我更熟悉C#,我会沿着selectedFruits.select(fruit=>fruit.id);的思路来做一些事情
是否有一些方法/现成的函数可以用javascript/jquery来做类似的事情?或者最简单的选择是循环遍历列表并创建第二个数组?我打算用JSON将数组发送回服务器,所以我试图最小化发送的数据。

qvk1mo1f

qvk1mo1f1#

是的,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较早的浏览器不支持www.example.com,所以我建议您继续使用jQuery方法。
如果你出于某种原因喜欢另一个,你可以随时添加一个polyfill来支持旧的浏览器。
您也可以随时将自定义方法添加到数组原型:

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 test来比较函数构造函数和对象文字的速度。如果你决定使用前者,请记住正确地引用字符串。
我个人的偏好是在筛选1-2个属性时使用基于对象文字的解决方案,并传递回调函数以进行更复杂的筛选。
我将以两个向本机对象原型添加方法的一般提示来结束本文:
1.在覆盖之前检查现有方法的出现情况,例如:
if(!Array.prototype.where) { Array.prototype.where = ...
1.如果你不需要支持IE8或更低版本,那么就用Object.defineProperty定义方法,使其成为不可枚举的。如果有人在数组上使用for..in(这首先是错误的),那么他们也会迭代可枚举属性。只是提醒一下。

x6h2sr28

x6h2sr282#

我知道这是一个迟来的答案,但它对我很有用!只是为了完成,使用$.grep函数,你可以模拟linq where()
林克:

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

4szc88ey3#

对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/

cyej8jka

cyej8jka4#

由于您使用的是knockout,因此应该考虑使用knockout实用函数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();
fslejnso

fslejnso5#

您也可以尝试linq.js
linq.js中,您的

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

将是

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

3yhwsihp6#

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

gupuwyp2

gupuwyp27#

最类似的C# Select类似函数是map函数。只需用途:

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

以从selectedFruits数组中选择所有ID。
它不需要任何外部依赖,只需要纯JavaScript。您可以在这里找到map文档:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map

sg3maiej

sg3maiej8#

看一下underscore.js,它提供了许多类似linq的函数,在你给予的例子中,你将使用map函数。

相关问题