2008-12-13 12 views
8

No es raro para mí (o probablemente para cualquier otra persona) tener una lista de objetos que necesito para iterar y luego interactuar con una lista de propiedades. Uso un ciclo anidado, como este:Llamando a compañeros nerds de código: ¿alternativas a los bucles anidados?

IList<T> listOfObjects; 
IList<TProperty> listOfProperties; 

foreach (T dataObject in listOfObjects) 
{ 
    foreach (TProperty property in listOfProperties) 
    { 
     //do something clever and extremely useful here 
    } 
} 

¿Este es el patrón de tiempo y rendimiento probado para este problema? ¿O hay algo más divertido, más elegante o simplemente divertido (mientras se puede leer y mantener, por supuesto)?

El código anterior no me hace sonreír. ¿Alguien puede por favor ayudar a traer algo de alegría a mi loop?

¡Gracias!

Actualización: uso el término "nerd" en el sentido más positivo. Como parte de la definición de wikipedia, "eso se refiere a una persona que realiza actividades intelectuales con pasión". ¡Por "codicioso" me refiero a alguien que está preocupado por mejorarse continuamente como programador, encontrando nuevas, novedosas y elegantes formas de codificación que son rápidas, fáciles de mantener y hermosas! Se regocijan por haberse mudado de VB6 y quieren que las personas inteligentes critiquen su código y los ayuden a actualizarse. (Nota: también les gusta hacer nuevas palabras que terminan en -ify).

Nota final:

Gracias a Dave R, Earwicker y TheSoftwareJedi por el envío por el camino LINQ. ¡Es el tipo de código feliz que estaba buscando!

+1

¿Por qué esta pregunta comienza con "nerds de código de llamada"? No me gusta el término "nerd". Este es un sitio para programadores. ¿Los "nerds del código" son un subconjunto de "programadores"? Tengo la sensación de que MrJeepster no se incluye en esa categoría, ¿se cree a sí mismo mejor que los "codiciosos"? – Guge

+0

Mucha gente aquí prefiere hablar de proceso en lugar de código. El continuo "¿por qué estás haciendo eso?" se pone un poco cansado al final. Me gusta;) – krosenvold

+0

Para los programadores de Java, http://homepages.mcs.vuw.ac.nz/~djp/jql/ es un punto de partida. Suponiendo que sus bucles anidados están destinados a detectar condiciones y coincidencias de igualdad; arriba haría el truco. Pero no si se necesitan reglas comerciales complejas. No sé el equivalente de C#, lo siento compañero – questzen

Respuesta

8

Parece que usted está tratando de unir dos listas cartesiana, y aplicar una cláusula where. Aquí hay un ejemplo simple que muestra la sintaxis de Linq para hacer esto, que creo que es lo que está buscando. list1 y list2 pueden ser IEnumerable, tu cláusula where puede contener una lógica más detallada, y en tu cláusula de selección puedes eliminar lo que necesites.

 var list1 = Enumerable.Range(1, 100); 
     var list2 = Enumerable.Range(1, 100); 

     foreach (var item in from a in list1 
          from b in list2 
          where a % b == 0 
          select new { a, b }) 
     { 
      Console.WriteLine(item); 
     }; 

rendimiento será idéntico a lo que envió sin embargo - ningún deseo de inducir a error en ese sentido. Prefiero esta sintaxis de Linq.

0

En un escenario de este tipo, a menudo a empezar por el filtrado de las piezas que nos interesan. su dosomethingclever bloque() por lo general comienza en

foreach (T dataObject in listOfObjects) 
{  
    foreach (TProperty property in listOfProperties)  
    { 
    if (property.something == "blah") 
    { // OK, we found the piece we're interested in... 

     // do something clever... 

    } 
    } 
} 

Aquí es donde LINQ es su amigo, lo que permite su para reemplazar sus bucles por una declaración selecta. Por supuesto, es posible que aún necesite iterar en el conjunto de resultados.

Tons of samples here.

3

Si necesita hacer algo con cada objeto y cada propiedad, no hay mucho por hacer. Es posible que pueda hacer algunas cosas sintácticamente agradables, pero no hay una forma de hacer el trabajo.

Si solo está trabajando en un subconjunto de los objetos y/o propiedades, filtúelo (con linq a los objetos, si está haciendo .net 3.5).

Puede disfrutar de Filter/Map/Reduce para sus conjuntos como un medio para introducir una mejor sintaxis para realizar operaciones de conjunto.

+0

Creo que está trabajando en algún resultado cartesiano de las listas, por lo que lo que haría no necesita ser criticado. Él solo está buscando una manera más elegante de escribirlo. Loops anidados chupar. – TheSoftwareJedi

+0

@TheSoftwareJedi - ¿Por qué chupan los bucles anidados? Me gustaría escuchar tu razonamiento. –

8

No hay nada de malo con los bucles anidados. Son rápidos, fáciles de leer y han existido desde que el desarrollo de software dio sus primeros pasos.

Como desea realizar acciones que lleva a iterar sobre una colección, es posible que LINQ sería una vía interesante para explorar:

http://msdn.microsoft.com/en-us/vcsharp/aa904594.aspx

Se le limitando a versiones posteriores de la Framework (3.5 en adelante), pero en realidad puede encontrar el enfoque de Programación Funcional bastante elegante. Otras características del lenguaje que entran en juego cuando vas por este camino incluyen lambdas y métodos anónimos, que son fascinantes por derecho propio.

mejor de las suertes y espero que se diviertan en el camino - que es un gran acercamiento :)

+0

Loops anidados puede ser un oso para leer. Linq ayuda con eso. – TheSoftwareJedi

+0

Maravillosa respuesta. Por supuesto, aquellos que piensan que los bucles anidados son ilegibles, como TheSoftwareJedi, pueden encontrarlos difíciles de leer. Aunque no veo por qué. –

5
foreach (var pair in from obj in listOfObjects 
        from prop in listOfProperties 
        select new {obj, prop}) 
{ 
    Console.WriteLine(pair.obj + ", " + pair.prop); 
} 
2
Action<T, TProp> somethingClever = //your clever method 

listOfObjects 
    .SelectMany(
    o => listOfProperties, 
    (o, p) => new {o, p}) 
    .ToList() 
    .ForEach(x => somethingClever(x.o, x.p)); 
+0

¡Esto parece aún más nerd! Oh, las opciones para un código feliz! Ahora, para convencer al líder del equipo de que permita la transición a 3.5 :( – Steve

0

me gusta Ayende de pipes and filters, pero es mucho más código que una función de LINQ para los bucles simples (que suponen el ejemplo de código en la pregunta era trivial).

2

Aunque me gusta la elegancia de las soluciones de Linq, creo que mi recomendación sería extraer el bucle interno en un método; Su código terminaría luciendo algo como:

foreach(dataObject in listOfObjects) 
    DoSomethingCleverWithProperties(dataObject, listOfProperties); 

Eso me parece más fácil de mantener.

Cuestiones relacionadas