簡體   English   中英

Javascript 等效於 C# LINQ Select

[英]Javascript Equivalent to C# LINQ Select

在此問題之后:

在淘汰賽中使用選中的綁定和復選框列表檢查所有復選框

我使用淘汰賽創建了一些復選框,允許從數組中進行選擇。 從上面的帖子中提取的工作小提琴:

http://jsfiddle.net/NsCXJ/

有沒有一種簡單的方法來創建一個只包含水果 ID 的數組?

我更喜歡使用 C#,在那里我會做一些類似selectedFruits.select(fruit=>fruit.id);

是否有一些方法/現成的函數可以做與 javascript/jquery 類似的事情? 或者最簡單的選擇是遍歷列表並創建第二個數組? 我打算將數組以 JSON 格式發回服務器,因此我試圖盡量減少發送的數據。

是的, 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 (這首先是錯誤的),他們也會迭代可枚舉的屬性。 只是抬頭。

我知道這是一個遲到的答案,但它對我很有用! 只是為了完成,使用$.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; });

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/

由於您正在使用淘汰賽,您應該考慮使用淘汰賽實用函數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") // 1 of 3 different ways to specify a selector function
    .ToArray();

你也可以試試linq.js

linq.js

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

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

我在TsLinq.codeplex.com下為 TypeScript 構建了一個 Linq 庫,您也可以將其用於純 javascript。 該庫比 Linq.js 快 2-3 倍,並包含所有 Linq 方法的單元測試。 也許你可以回顧一下那個。

看一看underscore.js ,它提供了許多類似 linq 的功能。 在您提供的示例中,您將使用 map 函數。

你可以試試manipula包,它實現了所有的 C# LINQ 方法並保存了它的語法: https : //github.com/litichevskiydv/manipula

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

你的例子selectedFruits.select(fruit=>fruit.id); 將通過操縱桿實現

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

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

Dinqyjs具有類似 linq 的語法,並為 map 和 indexOf 等函數提供polyfill ,並且專門為在 Javascript 中處理數組而設計。

看看fluent ,它幾乎支持 LINQ 所做的所有事情,並且基於可迭代對象 - 因此它可以與地圖、生成器函數、數組以及所有可迭代對象一起使用。

不得不合並這個不錯的答案。 它揭示了類似的東西;

延期;

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

用法;



masterTableView.get_dataItems().where(function (t) {
if (t.findElement("_invoiceGridCheckbox").checked) {
    invoiceIds.push(t.getDataKeyValue("Id"));
  }
});

至於 2021 年,LINQ to object 的完整實現是用 ECMAScript (javascript) 的最新功能編寫的。

Github 存儲庫是: https : //github.com/IlanAmoyal/WebPartyLinq

我正在回答問題的標題,而不是更具體的原始問題。

有了迭代器、生成器函數和對象等 Javascript 的新特性,像 LINQ for Javascript 這樣的東西成為可能。 請注意,以 linq.js 為例,它使用了一種完全不同的方法,即使用正則表達式,這可能是為了克服當時該語言缺乏支持的問題。

話雖如此,我已經為 Javascript 編寫了一個 LINQ 庫,您可以在https://github.com/Siderite/LInQer 上找到它。 https://siderite.dev/blog/linq-in-javascript-linqer 上的評論和討論。

從以前的答案來看,似乎只有 Manipula 是人們對 Javascript 中的 LINQ 端口所期望的。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM