Aquí podría ser tu PUBLICIDAD


SelectMany Three Levels Deep

votos
17

Puedo aplanar los resultados de una colección infantil dentro de una colección con SelectMany:

 // a list of Foos, a Foo contains a List of Bars
 var source = new List<Foo>() { ... };

 var q = source.SelectMany(foo => foo.Bar)
     .Select(bar => bar.barId)
 .ToList();

esto me da la lista de todos los Ids de Bar en la Lista de Foo. Cuando intento recorrer tres niveles, se devuelve el resultado incorrecto.

 var q = source.SelectMany(foo => foo.Bar)
     .SelectMany(bar => bar.Widget)
         .Select(widget => widget.WidgetId)
 .ToList();

¿Cómo debería usar SelectMany para obtener la lista de todos los widgets en todas las barras de mi lista de Foos?

Editar . Perdí la frase anterior, pero el código refleja el objetivo. Estoy buscando una lista de todos los Id de widget, no widgets.

Un resultado incorrecto no es la devolución de todos los identificadores de widget.

Publicado el 12/03/2009 a las 21:48
fuente por usuario blu
En otros idiomas...        العربية       

3 respuestas

votos
31

Su consulta devuelve todos los ID de widget, en lugar de todos los widgets. Si solo quieres widgets, solo usa:

var q = source.SelectMany(foo => foo.Bar)
              .SelectMany(bar => bar.Widget)
              .ToList();

Si eso sigue dando "el resultado incorrecto", explique de qué forma es el resultado incorrecto. El código de muestra sería muy útil :)

EDITAR: De acuerdo, si quieres los ID de widget, tu código original debería estar bien:

var q = source.SelectMany(foo => foo.Bar)
              .SelectMany(bar => bar.Widget)
              .Select(widget => widget.WidgetId)
              .ToList();

Eso también podría escribirse como

var q = (from foo in source
         from bar in foo.Bar
         from widget in bar.Widget
         select widgetId).ToList();

si te gusta el formato de expresión de consulta

Esto realmente debería funcionar: si no funciona, eso sugiere que hay algo mal con sus datos.

Deberíamos haberlo verificado antes: ¿esto es solo LINQ to Objects o un proveedor más elegante (por ejemplo, LINQ to SQL)?

Respondida el 12/03/2009 a las 09:51
fuente por usuario Jon Skeet


Aquí podría ser tu PUBLICIDAD


votos
2
var q = (
    from f in foo
    from b in f.Bars
    from w in b.Widgets
    select w.WidgetId
   ).ToList();

También tenga en cuenta que si desea la lista única, puede hacer .Distinct (). ToList () en su lugar.

Respondida el 12/03/2009 a las 09:51
fuente por usuario eglasius

votos
1
       var q = source.SelectMany(foo => foo.Bar)
          .SelectMany(bar => bar.Widget,(bar,widget) => widget.WidgetId)
          .ToList();

podemos llamar a esta sobrecarga de SelectMany () con nos permite especificar la proyección usando experession lambda

Respondida el 29/01/2013 a las 03:43
fuente por usuario Abdalwhab Bakheet