javascript - alternative - linq js select example
Javascript Equivalente a C#LINQ Select (8)
Como está utilizando el knockout, debería considerar usar la función de utilidad knockout arrayMap()
y sus otras funciones de utilidad de matriz.
Aquí hay una lista de funciones de utilidad de matriz y sus métodos LINQ equivalentes:
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)
Entonces, lo que podrías hacer en tu ejemplo es esto:
var mapped = ko.utils.arrayMap(selectedFruits, function (fruit) {
return fruit.id;
});
Si desea una interfaz tipo LINQ en javascript, puede usar una biblioteca como linq.js que ofrece una buena interfaz para muchos de los métodos LINQ.
var mapped = Enumerable.From(selectedFruits)
.Select("$.id") // 1 of 3 different ways to specify a selector function
.ToArray();
Siguiendo esta pregunta aquí:
Creé algunas casillas usando knockout que permiten la selección de una matriz. violín de trabajo tomado de la publicación anterior:
¿Existe una manera simple de crear una matriz de solo las identificaciones de la fruta?
Estoy más en casa con C # donde haría algo como " selectedFruits.select(fruit=>fruit.id);
¿Hay algún método / función preparada para hacer algo similar con javascript / jquery? ¿O la opción más simple sería recorrer la lista y crear una segunda matriz? Tengo la intención de publicar la matriz de nuevo en el servidor en JSON, así que estoy tratando de minimizar los datos enviados.
Eche un vistazo a underscore.js que proporciona muchas funciones tipo linq. En el ejemplo que le das utilizaría la función de mapa.
He creado una biblioteca Linq para TypeScript bajo TsLinq.codeplex.com que puedes usar también para javascript. Esa biblioteca es 2-3 veces más rápida que Linq.js y contiene pruebas unitarias para todos los métodos de Linq. Tal vez podrías revisar eso.
La forma 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);
}
también en: https://jsfiddle.net/52dpucey/
Sé que es una respuesta tardía, pero fue útil para mí. Solo para completar, usando la función $.grep
puedes emular el 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; });
Sí, Array.map() o $.map() hace lo mismo.
//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);
Como array.map no es compatible con navegadores antiguos, le sugiero que se quede con el método jQuery.
Si prefiere el otro por algún motivo, siempre puede agregar un relleno múltiple para el soporte del navegador anterior.
Siempre puede agregar métodos personalizados al prototipo de matriz:
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;
});
Una versión extendida que utiliza el constructor de funciones si pasa una cadena. Algo para jugar con quizás:
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''));
Actualizar:
Dado que esto se ha convertido en una respuesta tan popular, estoy agregando mis similares where()
+ firstOrDefault()
. Estos también podrían usarse con el enfoque de constructor de funciones basado en cadenas (que es el más rápido), pero aquí hay otro enfoque que usa un literal de objeto como filtro:
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;
};
Uso:
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'' });
Aquí hay una prueba jsperf para comparar el constructor de la función contra la velocidad literal del objeto. Si decide usar el primero, tenga en cuenta para citar cadenas correctamente.
Mi preferencia personal es utilizar las soluciones basadas en el objeto literal al filtrar 1-2 propiedades, y pasar una función de devolución de llamada para un filtrado más complejo.
Terminaré esto con 2 consejos generales cuando agregue métodos a prototipos de objetos nativos:
Compruebe la existencia de métodos existentes antes de sobrescribir, por ejemplo:
if(!Array.prototype.where) { Array.prototype.where = ...
Si no necesita admitir IE8 y siguientes, defina los métodos utilizando Object.defineProperty para que no sean enumerables. Si alguien usó ...
for..in
en una matriz (lo cual está mal en primer lugar) también iterará las propiedades enumerables. Solo un aviso.
Dinqyjs tiene una sintaxis similar a linq y proporciona polyfills para funciones como map e indexOf, y ha sido diseñado específicamente para trabajar con arrays en Javascript.