Desafortunadamente, no tengo JQuery o Underscore, solo javascript puro (compatible con IE9).
Quiero el equivalente de SelectMany () de la funcionalidad LINQ.
// SelectMany flattens it to just a list of phone numbers.
IEnumerable<PhoneNumber> phoneNumbers = people.SelectMany(p => p.PhoneNumbers);
¿Puedo hacerlo?
EDITAR:
Gracias a las respuestas, conseguí que esto funcionara:
var petOwners =
[
{
Name: "Higa, Sidney", Pets: ["Scruffy", "Sam"]
},
{
Name: "Ashkenazi, Ronen", Pets: ["Walker", "Sugar"]
},
{
Name: "Price, Vernette", Pets: ["Scratches", "Diesel"]
},
];
function property(key){return function(x){return x[key];}}
function flatten(a,b){return a.concat(b);}
var allPets = petOwners.map(property("Pets")).reduce(flatten,[]);
console.log(petOwners[0].Pets[0]);
console.log(allPets.length); // 6
var allPets2 = petOwners.map(function(p){ return p.Pets; }).reduce(function(a, b){ return a.concat(b); },[]); // all in one line
console.log(allPets2.length); // 6
javascript
c#
Toddmo
fuente
fuente
Respuestas:
para una selección simple, puede usar la función de reducción de Array.
Digamos que tiene una matriz de matrices de números:
var arr = [[1,2],[3, 4]]; arr.reduce(function(a, b){ return a.concat(b); }); => [1,2,3,4] var arr = [{ name: "name1", phoneNumbers : [5551111, 5552222]},{ name: "name2",phoneNumbers : [5553333] }]; arr.map(function(p){ return p.phoneNumbers; }) .reduce(function(a, b){ return a.concat(b); }) => [5551111, 5552222, 5553333]
Editar:
dado que es6 flatMap se ha agregado al prototipo de Array.
SelectMany
es sinónimo deflatMap
.El método primero mapea cada elemento usando una función de mapeo, luego aplana el resultado en una nueva matriz. Su firma simplificada en TypeScript es:
function flatMap<A, B>(f: (value: A) => B[]): B[]
Para lograr la tarea solo necesitamos flatMap cada elemento a phoneNumbers
arr.flatMap(a => a.phoneNumbers);
fuente
arr.reduce(function(a, b){ return a.concat(b.phoneNumbers); }, [])
flatMap
no cumple con la solicitud del OP de una solución compatible con IE9: compatibilidad del navegador paraflatmap
.Como opción más simple, Array.prototype.flatMap () o Array.prototype.flat ()
const data = [ {id: 1, name: 'Dummy Data1', details: [{id: 1, name: 'Dummy Data1 Details'}, {id: 1, name: 'Dummy Data1 Details2'}]}, {id: 1, name: 'Dummy Data2', details: [{id: 2, name: 'Dummy Data2 Details'}, {id: 1, name: 'Dummy Data2 Details2'}]}, {id: 1, name: 'Dummy Data3', details: [{id: 3, name: 'Dummy Data3 Details'}, {id: 1, name: 'Dummy Data3 Details2'}]}, ] const result = data.flatMap(a => a.details); // or data.map(a => a.details).flat(1); console.log(result)
fuente
const result = data.flatMap(a => a.details)
Para aquellos que un tiempo después, entienden javascript pero aún quieren un método simple Typed SelectMany en Typecript:
function selectMany<TIn, TOut>(input: TIn[], selectListFn: (t: TIn) => TOut[]): TOut[] { return input.reduce((out, inx) => { out.push(...selectListFn(inx)); return out; }, new Array<TOut>()); }
fuente
Sagi tiene razón al usar el método concat para aplanar una matriz. Pero para obtener algo similar a este ejemplo, también necesitaría un mapa para la parte seleccionada https://msdn.microsoft.com/library/bb534336(v=vs.100).aspx
/* arr is something like this from the example PetOwner[] petOwners = { new PetOwner { Name="Higa, Sidney", Pets = new List<string>{ "Scruffy", "Sam" } }, new PetOwner { Name="Ashkenazi, Ronen", Pets = new List<string>{ "Walker", "Sugar" } }, new PetOwner { Name="Price, Vernette", Pets = new List<string>{ "Scratches", "Diesel" } } }; */ function property(key){return function(x){return x[key];}} function flatten(a,b){return a.concat(b);} arr.map(property("pets")).reduce(flatten,[])
fuente
arr
conpeople
y"pets"
con"PhoneNumbers"
petOwners.map(owner => owner.Pets).reduce((a, b) => a.concat(b), []);
. O, aún más simple,petOwners.reduce((a, b) => a.concat(b.Pets), []);
.// you can save this function in a common js file of your project function selectMany(f){ return function (acc,b) { return acc.concat(f(b)) } } var ex1 = [{items:[1,2]},{items:[4,"asda"]}]; var ex2 = [[1,2,3],[4,5]] var ex3 = [] var ex4 = [{nodes:["1","v"]}]
Empecemos
ex1.reduce(selectMany(x=>x.items),[])
=> [1, 2, 4, "asda"]
ex2.reduce(selectMany(x=>x),[])
=> [1, 2, 3, 4, 5]
ex3.reduce(selectMany(x=> "this will not be called" ),[])
=> []
ex4.reduce(selectMany(x=> x.nodes ),[])
=> ["1", "v"]
NOTA: use una matriz válida (no nula) como valor inicial en la función de reducción
fuente
prueba esto (con es6):
Array.prototype.SelectMany = function (keyGetter) { return this.map(x=>keyGetter(x)).reduce((a, b) => a.concat(b)); }
matriz de ejemplo:
var juices=[ {key:"apple",data:[1,2,3]}, {key:"banana",data:[4,5,6]}, {key:"orange",data:[7,8,9]} ]
utilizando :
juices.SelectMany(x=>x.data)
fuente
Yo haría esto (evitando .concat ()):
function SelectMany(array) { var flatten = function(arr, e) { if (e && e.length) return e.reduce(flatten, arr); else arr.push(e); return arr; }; return array.reduce(flatten, []); } var nestedArray = [1,2,[3,4,[5,6,7],8],9,10]; console.log(SelectMany(nestedArray)) //[1,2,3,4,5,6,7,8,9,10]
Si no desea utilizar .reduce ():
function SelectMany(array, arr = []) { for (let item of array) { if (item && item.length) arr = SelectMany(item, arr); else arr.push(item); } return arr; }
Si desea utilizar .forEach ():
function SelectMany(array, arr = []) { array.forEach(e => { if (e && e.length) arr = SelectMany(e, arr); else arr.push(e); }); return arr; }
fuente
Aquí tiene, una versión reescrita de la respuesta de joel-harkes en TypeScript como una extensión, utilizable en cualquier matriz. Así que literalmente puedes usarlo como
somearray.selectMany(c=>c.someprop)
. Transpilado, esto es javascript.declare global { interface Array<T> { selectMany<TIn, TOut>(selectListFn: (t: TIn) => TOut[]): TOut[]; } } Array.prototype.selectMany = function <TIn, TOut>( selectListFn: (t: TIn) => TOut[]): TOut[] { return this.reduce((out, inx) => { out.push(...selectListFn(inx)); return out; }, new Array<TOut>()); } export { };
fuente
Puede probar el
manipula
paquete que implementa todos los métodos C # LINQ y conserva su sintaxis:Manipula.from(petOwners).selectMany(x=>x.Pets).toArray()
https://github.com/litichevskiydv/manipula
https://www.npmjs.com/package/manipula
fuente