Diferencia entre Select y SelectMany
Frecuentes
Visto 561,018 veces
1151
He estado buscando la diferencia entre Select
y SelectMany
pero no he podido encontrar una respuesta adecuada. Necesito aprender la diferencia al usar LINQ To SQL, pero todo lo que he encontrado son ejemplos de matrices estándar.
¿Alguien puede proporcionar un ejemplo de LINQ To SQL?
17 Respuestas
1712
SelectMany
aplana las consultas que devuelven listas de listas. Por ejemplo
public class PhoneNumber
{
public string Number { get; set; }
}
public class Person
{
public IEnumerable<PhoneNumber> PhoneNumbers { get; set; }
public string Name { get; set; }
}
IEnumerable<Person> people = new List<Person>();
// Select gets a list of lists of phone numbers
IEnumerable<IEnumerable<PhoneNumber>> phoneLists = people.Select(p => p.PhoneNumbers);
// SelectMany flattens it to just a list of phone numbers.
IEnumerable<PhoneNumber> phoneNumbers = people.SelectMany(p => p.PhoneNumbers);
// And to include data from the parent in the result:
// pass an expression to the second parameter (resultSelector) in the overload:
var directory = people
.SelectMany(p => p.PhoneNumbers,
(parent, child) => new { parent.Name, child.Number });
Respondido el 29 de Septiembre de 17 a las 11:09
Pregunta relacionada al anidar SelectMany para aplanar una estructura jerárquica anidada. - El guisante rojo
Para comprender más resultSelector El siguiente enlace ayuda blogs.interknowlogy.com/2008/10/10/… - jamir
Una demostración más con resultados de los padres: dotnetfiddle.net/flcdCC - Evgeni Kosjakov
210
Seleccionar muchos es como operación de unión cruzada en SQL donde lleva el producto cruzado.
Por ejemplo si tenemos
Set A={a,b,c}
Set B={x,y}
Seleccionar muchos se puede utilizar para obtener el siguiente conjunto
{ (x,a) , (x,b) , (x,c) , (y,a) , (y,b) , (y,c) }
Tenga en cuenta que aquí tomamos todas las combinaciones posibles que se pueden hacer a partir de los elementos del conjunto A y del conjunto B.
Aquí hay un ejemplo de LINQ que puede probar
List<string> animals = new List<string>() { "cat", "dog", "donkey" };
List<int> number = new List<int>() { 10, 20 };
var mix = number.SelectMany(num => animals, (n, a) => new { n, a });
la mezcla tendrá los siguientes elementos en estructura plana como
{(10,cat), (10,dog), (10,donkey), (20,cat), (20,dog), (20,donkey)}
Respondido 12 Jul 18, 13:07
Sé que esto es viejo, pero quería agradecerles por esto, ¡me salvó mucho! :) También puede ser útil tener una referencia a esos códigos: stackoverflow.com/questions/3479980/… ¡Salud! - user3439065
SelectMany no tiene que usarse así. También tiene la opción de tomar solo una función. - barlop
No sé si es correcto decir que así es como SelectMany
is. Más bien, esta es una forma en que SelectMany
se puede usar, pero en realidad no es la forma normal de usarlo. - Dave Cousineau
Esta fue la respuesta más sencilla de entender para mí. - Jaim Eliyah
133
var players = db.SoccerTeams.Where(c => c.Country == "Spain")
.SelectMany(c => c.players);
foreach(var player in players)
{
Console.WriteLine(player.LastName);
}
- De Gea
- Alba
- Costa
- Villa
- Busquets
...
Respondido 23 Abr '19, 19:04
76
SelectMany()
le permite colapsar una secuencia multidimensional de una manera que de otra manera requeriría un segundo Select()
o bucle.
Más detalles en este blog.
Respondido 21 Abr '15, 17:04
Pero el primero devuelve el tipo Enumerables de Hijos, el segundo ejemplo devuelve el tipo de Padres. En realidad, estoy un poco confundido, ¿lo abrirías un poco más? - Tarik
Al revés, en realidad. El segundo aplanará por completo la jerarquía de enumerables, de modo que recupere a los niños. Pruebe el artículo en el enlace que agregué, vea si eso ayuda. - miguel petrotta
El primero no parece ser legal. Creo que el cartel se confundió. El segundo devolvería una enumeración de padres. - mqp
Gracias, bueno, en realidad sí, los ejemplos fueron un poco confusos aunque :) pero gracias de nuevo por intentar ayudarme. - Tarik
38
Hay varias sobrecargas para SelectMany
. Uno de ellos le permite realizar un seguimiento de cualquier relación entre padres e hijos mientras atraviesa la jerarquía.
Ejemplo: suponga que tiene la siguiente estructura: League -> Teams -> Player
.
Puede devolver fácilmente una colección plana de jugadores. Sin embargo, puede perder cualquier referencia al equipo del que forma parte el jugador.
Afortunadamente existe una sobrecarga para tal fin:
var teamsAndTheirLeagues =
from helper in leagues.SelectMany
( l => l.Teams
, ( league, team ) => new { league, team } )
where helper.team.Players.Count > 2
&& helper.league.Teams.Count < 10
select new
{ LeagueID = helper.league.ID
, Team = helper.team
};
El ejemplo anterior está tomado de Blog de IK de Dan. Te recomiendo encarecidamente que le eches un vistazo.
Respondido 12 Jul 18, 13:07
22
Entiendo SelectMany
para que funcione como un atajo de combinación.
Así que puedes:
var orders = customers
.Where(c => c.CustomerName == "Acme")
.SelectMany(c => c.Orders);
Respondido 06 Abr '20, 09:04
El ejemplo proporcionado funciona, pero Seleccionar muchos no funciona exactamente como una combinación. Una combinación permite "usar" cualquier campo de la tabla original más cualquier campo de la tabla combinada. Pero aquí debe especificar un objeto de una lista adjunta a la tabla original. Por ejemplo, .SelectMany(c => new {c.CompanyName, c.Orders.ShippedDate});
no funcionaría. SelectMany es más bien aplanar la lista de listas, y puede elegir cualquiera (pero solo una a la vez) de las listas contenidas para el resultado. Para comparacion: Unión interior en Linq. - Matt
14
Select es una proyección simple uno a uno desde el elemento de origen hasta un elemento de resultado. Select- Many se usa cuando hay varias cláusulas from en una expresión de consulta: cada elemento de la secuencia original se usa para generar una nueva secuencia.
Respondido el 25 de Septiembre de 12 a las 10:09
14
EL Seleccionar muchos () el método se utiliza para aplanar una secuencia en la que cada uno de los elementos de la secuencia es independiente.
tengo clase user
igual que esto
class User
{
public string UserName { get; set; }
public List<string> Roles { get; set; }
}
principal:
var users = new List<User>
{
new User { UserName = "Reza" , Roles = new List<string>{"Superadmin" } },
new User { UserName = "Amin" , Roles = new List<string>{"Guest","Reseption" } },
new User { UserName = "Nima" , Roles = new List<string>{"Nurse","Guest" } },
};
var query = users.SelectMany(user => user.Roles, (user, role) => new { user.UserName, role });
foreach (var obj in query)
{
Console.WriteLine(obj);
}
//output
//{ UserName = Reza, role = Superadmin }
//{ UserName = Amin, role = Guest }
//{ UserName = Amin, role = Reseption }
//{ UserName = Nima, role = Nurse }
//{ UserName = Nima, role = Guest }
Puede utilizar operaciones en cualquier elemento de la secuencia.
int[][] numbers = {
new[] {1, 2, 3},
new[] {4},
new[] {5, 6 , 6 , 2 , 7, 8},
new[] {12, 14}
};
IEnumerable<int> result = numbers
.SelectMany(array => array.Distinct())
.OrderBy(x => x);
//output
//{ 1, 2 , 2 , 3, 4, 5, 6, 7, 8, 12, 14 }
List<List<int>> numbers = new List<List<int>> {
new List<int> {1, 2, 3},
new List<int> {12},
new List<int> {5, 6, 5, 7},
new List<int> {10, 10, 10, 12}
};
IEnumerable<int> result = numbers
.SelectMany(list => list)
.Distinct()
.OrderBy(x=>x);
//output
// { 1, 2, 3, 5, 6, 7, 10, 12 }
Respondido el 19 de junio de 20 a las 21:06
¿Qué pasa si una o más de las listas resultan ser nulas, aún puede agregar las otras? Recibo un error porque tengo un par de resultados nulos. - Barra
8
Es posible que algunos SelectMany no sean necesarios. A continuación, 2 consultas dan el mismo resultado.
Customers.Where(c=>c.Name=="Tom").SelectMany(c=>c.Orders)
Orders.Where(o=>o.Customer.Name=="Tom")
Para una relación de 1 a muchos,
- si Start from "1", SelectMany es necesario, aplana los muchos.
- si Empezar desde "Muchos", no se necesita SeleccionarMuchos. (todavía se puede filtrar desde "1", también esto es más simple que la siguiente consulta de unión estándar)
from o in Orders
join c in Customers on o.CustomerID equals c.ID
where c.Name == "Tom"
select o
Respondido el 22 de Septiembre de 17 a las 21:09
5
Sin ser demasiado técnico, base de datos con muchas organizaciones, cada una con muchos usuarios: -
var orgId = "123456789";
var userList1 = db.Organizations
.Where(a => a.OrganizationId == orgId)
.SelectMany(a => a.Users)
.ToList();
var userList2 = db.Users
.Where(a => a.OrganizationId == orgId)
.ToList();
ambos regresan lo mismo Aplicación Lista de usuarios para la organización seleccionada.
Los primeros "proyectos" de la organización a los usuarios, el segundo consulta la tabla de usuarios directamente.
contestado el 25 de mayo de 17 a las 16:05
4
Es más claro cuando la consulta devuelve una cadena (una matriz de caracteres):
Por ejemplo, si la lista 'Frutas' contiene 'manzana'
'Seleccionar' devuelve la cadena:
Fruits.Select(s=>s)
[0]: "apple"
'SelectMany' aplana la cadena:
Fruits.SelectMany(s=>s)
[0]: 97 'a'
[1]: 112 'p'
[2]: 112 'p'
[3]: 108 'l'
[4]: 101 'e'
respondido 28 mar '18, 15:03
3
Solo para una vista alternativa que puede ayudar a algunos programadores funcionales:
Select
ismap
SelectMany
isbind
(oflatMap
para su gente de Scala / Kotlin)
Respondido 12 Oct 17, 08:10
3
Considere este ejemplo:
var array = new string[2]
{
"I like what I like",
"I like what you like"
};
//query1 returns two elements sth like this:
//fisrt element would be array[5] :[0] = "I" "like" "what" "I" "like"
//second element would be array[5] :[1] = "I" "like" "what" "you" "like"
IEnumerable<string[]> query1 = array.Select(s => s.Split(' ')).Distinct();
//query2 return back flat result sth like this :
// "I" "like" "what" "you"
IEnumerable<string> query2 = array.SelectMany(s => s.Split(' ')).Distinct();
Como puede ver, los valores duplicados como "I" o "me gusta" se han eliminado de query2 porque "SelectMany" aplana y proyecta en varias secuencias. Pero query1 devuelve una secuencia de matrices de cadenas. y dado que hay dos matrices diferentes en query1 (primer y segundo elemento), no se eliminaría nada.
Respondido el 08 de diciembre de 19 a las 19:12
probablemente sea mejor incluir ahora .Distinct () al final y decir que genera "I" "like" "qué" "I" "like" "I" "like" "what" "you" "like" - Profe
2
Un ejemplo más de cómo se puede usar SelectMany + Select para acumular datos de objetos de submatriz.
Supongamos que tenemos usuarios con sus teléfonos:
class Phone {
public string BasePart = "555-xxx-xxx";
}
class User {
public string Name = "Xxxxx";
public List<Phone> Phones;
}
Ahora tenemos que seleccionar BaseParts de todos los teléfonos de todos los usuarios:
var usersArray = new List<User>(); // array of arrays
List<string> allBaseParts = usersArray.SelectMany(ua => ua.Phones).Select(p => p.BasePart).ToList();
Respondido 09 ago 18, 12:08
¿Cuál piensas que es mejor? Tuyo o usersArray.SelectMany(ua => ua.Phones.Select(p => p.BasePart))
- Michael mejor
1
EL SelectMany
método derriba un IEnumerable<IEnumerable<T>>
en una IEnumerable<T>
, como el comunismo, todos los elementos se comportan de la misma manera (un tonto tiene los mismos derechos que un genio).
var words = new [] { "a,b,c", "d,e", "f" };
var splitAndCombine = words.SelectMany(x => x.Split(','));
// returns { "a", "b", "c", "d", "e", "f" }
respondido 30 mar '20, 06:03
0
Aquí hay un ejemplo de código con una pequeña colección inicializada para probar:
class Program
{
static void Main(string[] args)
{
List<Order> orders = new List<Order>
{
new Order
{
OrderID = "orderID1",
OrderLines = new List<OrderLine>
{
new OrderLine
{
ProductSKU = "SKU1",
Quantity = 1
},
new OrderLine
{
ProductSKU = "SKU2",
Quantity = 2
},
new OrderLine
{
ProductSKU = "SKU3",
Quantity = 3
}
}
},
new Order
{
OrderID = "orderID2",
OrderLines = new List<OrderLine>
{
new OrderLine
{
ProductSKU = "SKU4",
Quantity = 4
},
new OrderLine
{
ProductSKU = "SKU5",
Quantity = 5
}
}
}
};
//required result is the list of all SKUs in orders
List<string> allSKUs = new List<string>();
//With Select case 2 foreach loops are required
var flattenedOrdersLinesSelectCase = orders.Select(o => o.OrderLines);
foreach (var flattenedOrderLine in flattenedOrdersLinesSelectCase)
{
foreach (OrderLine orderLine in flattenedOrderLine)
{
allSKUs.Add(orderLine.ProductSKU);
}
}
//With SelectMany case only one foreach loop is required
allSKUs = new List<string>();
var flattenedOrdersLinesSelectManyCase = orders.SelectMany(o => o.OrderLines);
foreach (var flattenedOrderLine in flattenedOrdersLinesSelectManyCase)
{
allSKUs.Add(flattenedOrderLine.ProductSKU);
}
//If the required result is flattened list which has OrderID, ProductSKU and Quantity,
//SelectMany with selector is very helpful to get the required result
//and allows avoiding own For loops what according to my experience do code faster when
// hundreds of thousands of data rows must be operated
List<OrderLineForReport> ordersLinesForReport = (List<OrderLineForReport>)orders.SelectMany(o => o.OrderLines,
(o, ol) => new OrderLineForReport
{
OrderID = o.OrderID,
ProductSKU = ol.ProductSKU,
Quantity = ol.Quantity
}).ToList();
}
}
class Order
{
public string OrderID { get; set; }
public List<OrderLine> OrderLines { get; set; }
}
class OrderLine
{
public string ProductSKU { get; set; }
public int Quantity { get; set; }
}
class OrderLineForReport
{
public string OrderID { get; set; }
public string ProductSKU { get; set; }
public int Quantity { get; set; }
}
Respondido 16 Oct 19, 10:10
-5
Creo que es la mejor manera de entenderlo.
var query =
Enumerable
.Range(1, 10)
.SelectMany(ints => Enumerable.Range(1, 10), (a, b) => $"{a} * {b} = {a * b}")
.ToArray();
Console.WriteLine(string.Join(Environment.NewLine, query));
Console.Read();
Ejemplo de tabla de multiplicar.
Respondido 23 Feb 16, 02:02
Solo si el significado de "mejor" ha cambiado drásticamente. - Vahid Amiri
¿Entonces esta es la mejor manera de pensar? Entonces, ¿cuál es la forma difícil de pensar? - syed ali
No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas c# linq-to-sql linq or haz tu propia pregunta.
puede ver el código de SelectMany con una función o con dos funciones referenciasource.microsoft.com/#System.Core/System/Linq/… - barlop
Si está familiarizado con Kotlin, tiene implementaciones bastante similares para colecciones como map, también conocido como C # Select, y flatMap, también conocido como C # SelectMany. Básicamente, las funciones de extensión de la biblioteca estándar de Kotlin para colecciones tienen similitudes con la biblioteca C # Linq. - Arsenius