Compartir a través de


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

Enumerable.Select

Queryable.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

Enumerable.SelectMany

Queryable.SelectMany

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.

Ilustración conceptual de la acción de Select()

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.

Gráfico mostrando la acción de SelectMany().

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#)

Select (Cláusula, Visual Basic)

System.Linq