[英]Javascript Equivalent to C# LINQ Select
在此問題之后:
我使用淘汰賽創建了一些復選框,允許從數組中進行選擇。 從上面的帖子中提取的工作小提琴:
有沒有一種簡單的方法來創建一個只包含水果 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);
由於舊瀏覽器不支持 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'));
更新:
由於這已成為如此受歡迎的答案,因此我添加了類似的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 個一般提示結束本文:
在覆蓋之前檢查現有方法的出現,例如:
if(!Array.prototype.where) { Array.prototype.where = ...
如果您不需要支持 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();
我在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
看看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.