Pregunta

Con frecuencia me encuentro escribiendo código como este:

List<int> list = new List<int> { 1, 3, 5 };
foreach (int i in list) {
    Console.Write("{0}\t", i.ToString()); }
Console.WriteLine();

Mejor sería algo como esto:

List<int> list = new List<int> { 1, 3, 5 };
Console.WriteLine("{0}\t", list);

Sospecho que hay alguna forma inteligente de hacer esto, pero no la veo.¿Alguien tiene una solución mejor que el primer bloque?

¿Fue útil?

Solución

Hacer esto:

list.ForEach(i => Console.Write("{0}\t", i));

EDITAR:A otros que han respondido: los quiere a todos en la misma línea, con pestañas entre ellos.:)

Otros consejos

Un enfoque diferente, sólo por diversión:

Console.WriteLine(string.Join("\t", list));

Si hay un fragmento de código que repites todo el tiempo según No te repitas, debes ponerlo en tu propia biblioteca y llamarlo.Teniendo esto en cuenta, hay dos aspectos para obtener la respuesta correcta aquí.La primera es la claridad y brevedad en el código que llama a la función de la biblioteca.El segundo son las implicaciones de rendimiento de foreach.

Primero pensemos en la claridad y brevedad del código de llamada.

Puedes hacerlo de varias maneras:

  1. en bucle
  2. bucle foreach
  3. Colección.ParaCada

De todas las formas de hacer una lista foreach, ForEach con lamba es la más clara y breve.

list.ForEach(i => Console.Write("{0}\t", i));

Entonces, en esta etapa puede parecer que List.ForEach es el camino a seguir.Sin embargo, ¿cuál es el rendimiento de esto?Es cierto que en este caso el tiempo de escritura en la consola regirá el rendimiento del código.Cuando sabemos algo sobre el rendimiento de una característica particular del lenguaje, al menos deberíamos considerarlo.

De acuerdo a Medidas de rendimiento de foreach de Duston Campbell La forma más rápida de iterar la lista con código optimizado es utilizar un bucle for sin una llamada a List.Count.

Sin embargo, el bucle for es una construcción detallada.También se considera una forma muy iterativa de hacer las cosas que no coincide con la tendencia actual hacia los modismos funcionales.

Entonces, ¿podemos conseguir brevedad, claridad y rendimiento?Podemos hacerlo usando un método de extensión.En un mundo ideal, crearíamos un método de extensión en la Consola que toma una lista y la escribe con un delimitador.No podemos hacer esto porque la Consola es una clase estática y los métodos de extensión solo funcionan en instancias de clases.En su lugar, debemos colocar el método de extensión en la lista misma (según la sugerencia de David B):

public static void WriteLine(this List<int> theList)
{
  foreach (int i in list)
  {
    Console.Write("{0}\t", t.ToString());
  }
  Console.WriteLine();
}

Este código se va a utilizar en muchos lugares por lo que deberíamos realizar las siguientes mejoras:

  • En lugar de usar foreach, deberíamos usar la forma más rápida de iterar la colección, que es un bucle for con un recuento en caché.
  • Actualmente, solo se puede pasar Lista como argumento.Como función de biblioteca, podemos generalizarla con un pequeño esfuerzo.
  • El uso de Lista nos limita solo a Listas. El uso de IList permite que este código funcione también con matrices.
  • Dado que el método de extensión estará en una IList, debemos cambiar el nombre para que quede más claro en qué estamos escribiendo:

Así es como se vería el código de la función:

public static void WriteToConsole<T>(this IList<T> collection)
{
    int count = collection.Count();
    for(int i = 0;  i < count; ++i)
    {
        Console.Write("{0}\t", collection[i].ToString(), delimiter);
    }
    Console.WriteLine();
}

Podemos mejorar esto aún más permitiendo que el cliente pase el delimitador.Luego podríamos proporcionar una segunda función que escriba en la consola con el delimitador estándar como este:

public static void WriteToConsole<T>(this IList<T> collection)
{
    WriteToConsole<T>(collection, "\t");
}

public static void WriteToConsole<T>(this IList<T> collection, string delimiter)
{
    int count = collection.Count();
    for(int i = 0;  i < count; ++i)
    {
         Console.Write("{0}{1}", collection[i].ToString(), delimiter);
    }
    Console.WriteLine();
}

Así que ahora, dado que queremos una forma eficaz, breve y clara de escribir listas en la consola, tenemos una.Aquí está el código fuente completo, incluida una demostración del uso de la función de biblioteca:

using System;
using System.Collections.Generic;
using System.Linq;

namespace ConsoleWritelineTest
{
    public static class Extensions
    {
        public static void WriteToConsole<T>(this IList<T> collection)
        {
            WriteToConsole<T>(collection, "\t");
        }

        public static void WriteToConsole<T>(this IList<T> collection, string delimiter)
        {
            int count = collection.Count();
            for(int i = 0;  i < count; ++i)
            {
                Console.Write("{0}{1}", collection[i].ToString(), delimiter);
            }
            Console.WriteLine();
        }
    }

    internal class Foo
    {
        override public string ToString()
        {
            return "FooClass";
        }
    }

    internal class Program
    {

        static void Main(string[] args)
        {
            var myIntList = new List<int> {1, 2, 3, 4, 5};
            var myDoubleList = new List<double> {1.1, 2.2, 3.3, 4.4};
            var myDoubleArray = new Double[] {12.3, 12.4, 12.5, 12.6};
            var myFooList = new List<Foo> {new Foo(), new Foo(), new Foo()};
            // Using the standard delimiter /t
            myIntList.WriteToConsole();
            myDoubleList.WriteToConsole();
            myDoubleArray.WriteToConsole();
            myFooList.WriteToConsole();
            // Using our own delimiter ~
            myIntList.WriteToConsole("~");
            Console.Read();
        }
    }
}

=======================================================

Se podría pensar que este debería ser el final de la respuesta.Sin embargo, existe otra generalización que se puede hacer.De la pregunta de fatcat no queda claro si siempre está escribiendo en la consola.Quizás haya que hacer algo más en el foreach.En ese caso, la respuesta de Jason Bunting dará esa generalidad.Aquí está su respuesta nuevamente:

list.ForEach(i => Console.Write("{0}\t", i));

Esto es a menos que hagamos un refinamiento más en nuestros métodos de extensión y agreguemos FastForEach como se muestra a continuación:

public static void FastForEach<T>(this IList<T> collection, Action<T> actionToPerform)
    {
        int count = collection.Count();
        for (int i = 0; i < count; ++i)
        {
            actionToPerform(collection[i]);    
        }
        Console.WriteLine();
    }

Esto nos permite ejecutar cualquier código arbitrario contra cada elemento de la colección. utilizando el método de iteración más rápido posible.

Incluso podemos cambiar la función WriteToConsole para usar FastForEach

public static void WriteToConsole<T>(this IList<T> collection, string delimiter)
{
     collection.FastForEach(item => Console.Write("{0}{1}", item.ToString(), delimiter));
}

Ahora el código fuente completo, incluido un ejemplo de uso de FastForEach, es:

using System;
using System.Collections.Generic;
using System.Linq;

namespace ConsoleWritelineTest
{
    public static class Extensions
    {
        public static void WriteToConsole<T>(this IList<T> collection)
        {
            WriteToConsole<T>(collection, "\t");
        }

        public static void WriteToConsole<T>(this IList<T> collection, string delimiter)
        {
             collection.FastForEach(item => Console.Write("{0}{1}", item.ToString(), delimiter));
        }

        public static void FastForEach<T>(this IList<T> collection, Action<T> actionToPerform)
        {
            int count = collection.Count();
            for (int i = 0; i < count; ++i)
            {
                actionToPerform(collection[i]);    
            }
            Console.WriteLine();
        }
    }

    internal class Foo
    {
        override public string ToString()
        {
            return "FooClass";
        }
    }

    internal class Program
    {

        static void Main(string[] args)
        {
            var myIntList = new List<int> {1, 2, 3, 4, 5};
            var myDoubleList = new List<double> {1.1, 2.2, 3.3, 4.4};
            var myDoubleArray = new Double[] {12.3, 12.4, 12.5, 12.6};
            var myFooList = new List<Foo> {new Foo(), new Foo(), new Foo()};

            // Using the standard delimiter /t
            myIntList.WriteToConsole();
            myDoubleList.WriteToConsole();
            myDoubleArray.WriteToConsole();
            myFooList.WriteToConsole();

            // Using our own delimiter ~
            myIntList.WriteToConsole("~");

            // What if we want to write them to separate lines?
            myIntList.FastForEach(item => Console.WriteLine(item.ToString()));
            Console.Read();
        }
    }
}

nueva Lista {1, 3, 5}. ForEach(Console.WriteLine);

        List<int> a = new List<int>() { 1, 2, 3, 4, 5 };
        a.ForEach(p => Console.WriteLine(p));

editar:Ahhh se me adelantó.

list.ForEach(x=>Console.WriteLine(x));
List<int> list = new List<int> { 1, 3, 5 };
list.ForEach(x => Console.WriteLine(x));

Editar:¡Maldita sea!Tomó demasiado tiempo abrir Visual Studio para probarlo.

También puedes unirte:

var qwe = new List<int> {5, 2, 3, 8};
Console.WriteLine(string.Join("\t", qwe));
public static void WriteLine(this List<int> theList)
{
  foreach (int i in list)
  {
    Console.Write("{0}\t", t.ToString());
  }
  Console.WriteLine();
}

Entonces despúes...

list.WriteLine();
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top