Operaciones de proyección
Actualización: noviembre 2007
El término proyección se refiere a la operación de transformar un objeto en un nueva forma que, a menudo, consta sólo de aquellas propiedades que se utilizarán posteriormente. Utilizando la proyección, puede construir un nuevo tipo generado a partir de cada objeto. Puede proyectar una propiedad y realizar una función matemática sobre ella. También puede proyectar el objeto original sin cambiarlo.
Los métodos de operador de consulta estándar que realizan proyección se enumeran en la siguiente sección.
Métodos
Nombre del método |
Descripción |
Sintaxis de las expresiones de consulta de C# |
Sintaxis de las expresiones de consulta de Visual Basic |
Más información |
---|---|---|---|---|
Select |
Proyecta valores basados en una función de transformación. |
select |
Select |
|
SelectMany |
Proyecta secuencias de valores basados en una función de transformación y, a continuación, los condensa en una sola secuencia. |
Utilice varias cláusulas from |
Utilice varias cláusulas From |
Ejemplos de sintaxis de expresiones de consulta
Select
El ejemplo siguiente utiliza la cláusula select en C# o la cláusula Select en Visual Basic para proyectar la primera letra de cada cadena de una lista de cadenas.
Dim words As New List(Of String)(New String() {"an", "apple", "a", "day"})
Dim query = From word In words _
Select word.Substring(0, 1)
Dim sb As New System.Text.StringBuilder()
For Each letter As String In query
sb.AppendLine(letter)
Next
' Display the output.
MsgBox(sb.ToString())
' This code produces the following output:
' a
' a
' a
' d
List<string> words = new List<string>() { "an", "apple", "a", "day" };
var query = from word in words
select word.Substring(0, 1);
foreach (string s in query)
Console.WriteLine(s);
/* This code produces the following output:
a
a
a
d
*/
SelectMany
El ejemplo siguiente utiliza varias cláusulas from en C# o cláusulas From en Visual Basic para proyectar cada palabra de cada cadena de una lista de cadenas.
Dim phrases As New List(Of String)(New String() {"an apple a day", "the quick brown fox"})
Dim query = From phrase In phrases _
From word In phrase.Split(" "c) _
Select word
Dim sb As New System.Text.StringBuilder()
For Each str As String In query
sb.AppendLine(str)
Next
' Display the output.
MsgBox(sb.ToString())
' This code produces the following output:
' an
' apple
' a
' day
' the
' quick
' brown
' fox
List<string> phrases = new List<string>() { "an apple a day", "the quick brown fox" };
var query = from phrase in phrases
from word in phrase.Split(' ')
select word;
foreach (string s in query)
Console.WriteLine(s);
/* This code produces the following output:
an
apple
a
day
the
quick
brown
fox
*/
Comparación entre Select y SelectMany
El trabajo de Select() y SelectMany() es generar un valor de resultado (o valores) a partir de los valores de origen. Select() genera un valor de resultado para cada valor de origen. El resultado total es, por tanto, una colección que tiene el mismo número de elementos que la colección de origen. En contraste, SelectMany() genera un resultado total único que contiene subcolecciones concatenadas procedentes de cada valor de origen. La función de transformación que se pasa como un argumento a SelectMany() debe devolver una secuencia enumerable de valores para cada valor de origen. Estas secuencias enumerables se concatenan entonces mediante SelectMany() para crear una sola secuencia mayor.
Las dos ilustraciones siguientes muestran la diferencia conceptual entre las acciones de estos dos métodos. En cada caso, suponga que la función de selector (transformación) selecciona la matriz de flores de cada valor de origen.
Esta ilustración describe cómo Select() devuelve una colección que tiene el mismo número de elementos que la colección de origen.
Esta ilustración describe cómo SelectMany() concatena la secuencia intermedia de matrices en un valor de resultado final que contiene cada valor de cada matriz intermedia.
Ejemplo de código
En el siguiente ejemplo se compara el comportamiento de Select() y SelectMany(). El código crea un "ramo" de flores tomando los primeros dos elementos de cada lista de nombres de flores de la colección de origen. En este ejemplo, el "valor único" que la función de transformación Select<TSource, TResult>(IEnumerable<TSource>, Func<TSource, TResult>) utiliza es en sí mismo una colección de valores. Esto requiere el bucle foreach (For Each en Visual Basic) adicional para enumerar cada cadena de cada subsecuencia.
Class Bouquet
Public Flowers As List(Of String)
End Class
Sub SelectVsSelectMany()
Dim bouquets As New List(Of Bouquet)(New Bouquet() { _
New Bouquet With {.Flowers = New List(Of String)(New String() {"sunflower", "daisy", "daffodil", "larkspur"})}, _
New Bouquet With {.Flowers = New List(Of String)(New String() {"tulip", "rose", "orchid"})}, _
New Bouquet With {.Flowers = New List(Of String)(New String() {"gladiolis", "lily", "snapdragon", "aster", "protea"})}, _
New Bouquet With {.Flowers = New List(Of String)(New String() {"larkspur", "lilac", "iris", "dahlia"})}})
Dim output As New System.Text.StringBuilder
' Select()
Dim query1 = bouquets.Select(Function(b) b.Flowers)
output.AppendLine("Using Select():")
For Each flowerList In query1
For Each str As String In flowerList
output.AppendLine(str)
Next
Next
' SelectMany()
Dim query2 = bouquets.SelectMany(Function(b) b.Flowers)
output.AppendLine(vbCrLf & "Using SelectMany():")
For Each str As String In query2
output.AppendLine(str)
Next
' Display the output
MsgBox(output.ToString())
' This code produces the following output:
'
' Using Select():
' sunflower
' daisy
' daffodil
' larkspur
' tulip
' rose
' orchid
' gladiolis
' lily
' snapdragon
' aster
' protea
' larkspur
' lilac
' iris
' dahlia
' Using SelectMany()
' sunflower
' daisy
' daffodil
' larkspur
' tulip
' rose
' orchid
' gladiolis
' lily
' snapdragon
' aster
' protea
' larkspur
' lilac
' iris
' dahlia
End Sub
class Bouquet
{
public List<string> Flowers { get; set; }
}
static void SelectVsSelectMany()
{
List<Bouquet> bouquets = new List<Bouquet>() {
new Bouquet { Flowers = new List<string> { "sunflower", "daisy", "daffodil", "larkspur" }},
new Bouquet{ Flowers = new List<string> { "tulip", "rose", "orchid" }},
new Bouquet{ Flowers = new List<string> { "gladiolis", "lily", "snapdragon", "aster", "protea" }},
new Bouquet{ Flowers = new List<string> { "larkspur", "lilac", "iris", "dahlia" }}
};
// *********** Select ***********
IEnumerable<List<string>> query1 = bouquets.Select(bq => bq.Flowers);
// ********* SelectMany *********
IEnumerable<string> query2 = bouquets.SelectMany(bq => bq.Flowers);
Console.WriteLine("Results by using Select():");
// Note the extra foreach loop here.
foreach (IEnumerable<String> collection in query1)
foreach (string item in collection)
Console.WriteLine(item);
Console.WriteLine("\nResults by using SelectMany():");
foreach (string item in query2)
Console.WriteLine(item);
/* This code produces the following output:
Results by using Select():
sunflower
daisy
daffodil
larkspur
tulip
rose
orchid
gladiolis
lily
snapdragon
aster
protea
larkspur
lilac
iris
dahlia
Results by using SelectMany():
sunflower
daisy
daffodil
larkspur
tulip
rose
orchid
gladiolis
lily
snapdragon
aster
protea
larkspur
lilac
iris
dahlia
*/
}
Más sobre cómo proyectar
Vea también
Conceptos
Información general sobre operadores de consulta estándar
Referencia
select (Cláusula, Referencia de C#)