161

在此问题之后:

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

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

http://jsfiddle.net/NsCXJ/

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

我更喜欢使用 C#,我会做一些类似的事情selectedFruits.select(fruit=>fruit.id);

是否有一些方法/现成的功能可以用 javascript/jquery 做类似的事情?或者最简单的选择是遍历列表并创建第二个数组?我打算以 JSON 格式将数组发布回服务器,因此我试图最小化发送的数据。

4

13 回答 13

255

是的,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 方法。

如果出于某种原因你更喜欢另一个,你总是可以添加一个 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 测试,用于比较函数构造函数与对象字面量的速度。如果您决定使用前者,请记住正确引用字符串。

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

在向本机对象原型添加方法时,我将使用 2 个一般提示来结束这一点:

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

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

  2. 如果您不需要支持 IE8 及以下版本,请使用Object.defineProperty定义方法以使其不可枚举。如果有人for..in在数组上使用(这首先是错误的),他们也会迭代可枚举的属性。只是一个抬头。

于 2013-09-21T19:37:41.397 回答
33

我知道这是一个迟到的答案,但它对我很有用!只是为了完成,使用该$.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; });
于 2014-05-15T14:35:10.783 回答
17

由于您使用的是敲除,因此您应该考虑使用敲除实用程序函数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();
于 2013-09-21T22:12:09.730 回答
17

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/

于 2016-12-19T15:41:28.263 回答
11

你也可以试试linq.js

linq.js你的

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

将会

Enumerable.From(selectedFruits).Select(function (fruit) { return fruit.id;  });
于 2015-03-02T08:50:49.993 回答
3

我在TsLinq.codeplex.com下为 TypeScript 构建了一个 Linq 库,您也可以将其用于纯 JavaScript。该库比 Linq.js 快 2-3 倍,并且包含所有 Linq 方法的单元测试。也许你可以回顾一下。

于 2014-05-15T14:13:30.433 回答
3

最相似的 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

于 2020-05-12T20:09:39.730 回答
1

看看underscore.js,它提供了许多类似 linq 的功能。在您提供的示例中,您将使用 map 函数。

于 2013-09-21T19:47:19.123 回答
0

您可以尝试manipula包,它实现了所有 C# LINQ 方法并保存其语法: https ://github.com/litichevskiydv/manipula

https://www.npmjs.com/package/manipula

您的示例selectedFruits.select(fruit=>fruit.id); 将使用 manipula 实现

Manipula.from(selectedFruits).select(fruit=>fruit.id);
于 2019-03-12T04:57:16.333 回答
-1

Dinqyjs具有类似 linq 的语法,并为 map 和 indexOf 等函数提供 polyfill,并且专为在 Javascript 中处理数组而设计。

于 2015-01-02T00:33:33.967 回答
-1

看看fluent,它几乎支持 LINQ 所做的所有事情并基于可迭代对象——因此它适用于映射、生成器函数、数组,以及所有可迭代对象。

于 2020-04-23T20:28:21.953 回答
-1

我正在回答问题的标题,而不是更具体的原始问题。

有了 Javascript 的新特性,比如迭代器和生成器函数和对象,像 LINQ for Javascript 这样的东西成为可能。请注意,例如 linq.js 使用了一种完全不同的方法,使用正则表达式,这可能是为了克服当时语言中缺乏支持的问题。

话虽如此,我已经为 Javascript 编写了一个 LINQ 库,您可以在https://github.com/Siderite/LInQer找到它。在https://siderite.dev/blog/linq-in-javascript-linqer 发表评论和讨论。

从以前的答案来看,只有 Manipula 似乎是人们对 Javascript 中的 LINQ 端口所期望的。

于 2020-01-06T16:22:56.713 回答
-1

至于 2021 年,使用 ECMAScript (javascript) 的最新功能编写的 LINQ to object 的完整实现。

Github 存储库是: https ://github.com/IlanAmoyal/WebPartyLinq

于 2021-07-27T04:07:06.703 回答