Javascript équivalent à C # LINQ Select
suite à cette question ici :
j'ai créé quelques cases à cocher en utilisant knockout qui permettent la sélection à partir d'un tableau. violon de travail tiré d'en haut post:
y a-t-il une façon simple de créer une rangée de pièces D'identité du fruit?
je suis plus à la maison avec C# où je ferais quelque chose comme selectedFruits.select(fruit=>fruit.id);
y a-t-il une méthode/fonction prête à l'emploi pour faire quelque chose de similaire avec javascript/jquery? Ou l'option la plus simple serait-elle de boucler la liste et de créer un second tableau? J'ai l'intention de poster le tableau vers le serveur dans JSON donc j'essaie de minimiser les données envoyées.
8 réponses
Oui, "1519100920 Tableau.carte () ou $.map() fait la même chose.
//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);
depuis array.map n'est pas pris en charge dans les navigateurs plus anciens, je suggère que vous vous en teniez à la méthode jQuery.
si vous préférez l'autre pour une raison quelconque, vous pouvez toujours ajouter un polyfill pour l'ancien support du navigateur.
vous pouvez toujours ajouter des méthodes personnalisées au prototype du tableau aussi bien:
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;
});
une version étendue qui utilise le constructeur de fonction si vous passez une chaîne. Quelque chose à jouer avec peut-être:
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'));
mise à jour:
depuis qu'il est devenu si populaire réponse, j'ajoute similaire mon where()
+ firstOrDefault()
. Ceux-ci pourraient également être utilisés avec l'approche du constructeur de fonctions basé sur la chaîne de caractères (qui est la plus rapide), mais voici une autre approche utilisant un objet littéral comme filtre:
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;
};
Utilisation:
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' });
voici un test jsperf pour comparer la fonction constructeur vs objet Vitesse littérale. Si vous décidez d'utiliser l'ancien, gardez à l'esprit pour citer les chaînes correctement.
Ma préférence personnelle est d'utiliser l'objet literal based solutions lors du filtrage des propriétés 1-2, et passer une fonction de rappel pour un filtrage plus complexe.
je terminerai ceci avec 2 Conseils généraux lors de l'ajout de méthodes à des prototypes d'objets natifs:
-
vérifier l'occurrence des méthodes existantes avant d'écrire p. ex.:
if(!Array.prototype.where) { Array.prototype.where = ...
-
si vous n'avez pas besoin de supporter IE8 et ci-dessous, définissez les méthodes en utilisant L'objet .defineProperty pour les rendre non-énumérable. Si quelqu'un a utilisé
for..in
sur un tableau (ce qui est faux, en premier lieu,) ils itérer les propriétés énumérables. Juste un heads-up.
je sais que c'est une réponse tardive mais elle m'a été utile! Juste pour compléter, en utilisant la fonction $.grep
vous pouvez émuler la linq where()
.
Linq:
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; });
puisque vous utilisez knockout, vous devriez considérer l'utilisation de la fonction d'utilité de knockout arrayMap()
et ses autres fonctions d'utilité de tableau.
Voici une liste des fonctions Utilitaires du tableau et leurs méthodes LINQ équivalentes:
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)
donc ce que vous pourriez faire dans votre exemple est ceci:
var mapped = ko.utils.arrayMap(selectedFruits, function (fruit) {
return fruit.id;
});
si vous voulez une interface de type LINQ en javascript, vous pouvez utiliser une bibliothèque telle que linq.js qui offre une interface agréable à beaucoup de méthodes LINQ.
var mapped = Enumerable.From(selectedFruits)
.Select("$.id") // 1 of 3 different ways to specify a selector function
.ToArray();
vous pouvez également essayer linq.js
linq.js
votre
selectedFruits.select(fruit=>fruit.id);
sera
Enumerable.From(selectedFruits).Select(function (fruit) { return fruit.id; });
L'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);
}
aussi à: https://jsfiddle.net/52dpucey /
jetez un oeil à underscore.js qui fournit beaucoup de linq comme des fonctions. Dans l'exemple que vous donnez, vous utilisez la fonction map.
j'ai construit une bibliothèque Linq pour dactylographier sous TsLinq.codeplex.com que vous pouvez utiliser pour JavaScript simple aussi. Cette bibliothèque est 2 à 3 fois plus rapide que Linq.js et contient des tests unitaires pour toutes les méthodes Linq. Peut-être que vous pourriez examiner.