Domanda

Mi trovo spesso a scrivere codice come questo:

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

Sarebbe meglio qualcosa del genere:

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

Sospetto che ci sia un modo intelligente per farlo, ma non lo vedo.Qualcuno ha una soluzione migliore del primo blocco?

È stato utile?

Soluzione

Fai questo:

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

MODIFICARE:Per gli altri che hanno risposto: li vuole tutti sulla stessa linea, con le schede tra di loro.:)

Altri suggerimenti

Un approccio diverso, solo per divertimento:

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

Se c'è un pezzo di codice che ripeti continuamente secondo Non ripeterti, dovresti inserirlo nella tua libreria e chiamarlo così.Con questo in mente ci sono 2 aspetti per ottenere la risposta giusta qui.Il primo è la chiarezza e la brevità del codice che richiama la funzione di libreria.Il secondo riguarda le implicazioni sulle prestazioni di foreach.

Per prima cosa pensiamo alla chiarezza e alla brevità del codice chiamante.

Puoi fare foreach in diversi modi:

  1. per ciclo
  2. per ciascun ciclo
  3. Collection.ForEach

Tra tutti i modi per creare un foreach List.ForEach con un lamba è il più chiaro e breve.

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

Quindi in questa fase potrebbe sembrare che List.ForEach sia la strada da percorrere.Tuttavia, quali sono le prestazioni di questo?È vero che in questo caso il tempo di scrittura sulla console determinerà l'esecuzione del codice.Quando sappiamo qualcosa sull'esecuzione di una particolare caratteristica linguistica dovremmo certamente almeno prenderla in considerazione.

Secondo Misurazioni delle prestazioni di foreach secondo Duston Campbell il modo più veloce per scorrere l'elenco con codice ottimizzato è utilizzare un ciclo for senza una chiamata a List.Count.

Il ciclo for tuttavia è un costrutto dettagliato.È anche visto come un modo molto iterativo di fare le cose che non corrisponde alla tendenza attuale verso idiomi funzionali.

Quindi possiamo ottenere brevità, chiarezza e prestazioni?Possiamo utilizzare un metodo di estensione.In un mondo ideale creeremmo un metodo di estensione su Console che prende un elenco e lo scrive con un delimitatore.Non possiamo farlo perché Console è una classe statica e i metodi di estensione funzionano solo su istanze di classi.Dobbiamo invece inserire il metodo di estensione nell'elenco stesso (come suggerito da David B):

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

Questo codice verrà utilizzato in molti posti, quindi dovremmo apportare i seguenti miglioramenti:

  • Invece di usare foreach dovremmo usare il modo più veloce di iterare la raccolta che è un ciclo for con un conteggio memorizzato nella cache.
  • Attualmente solo List può essere passato come argomento.Essendo una funzione di libreria, possiamo generalizzarla con un piccolo sforzo.
  • L'uso di List ci limita solo agli elenchi, l'uso di IList consente a questo codice di funzionare anche con gli array.
  • Poiché il metodo di estensione sarà su un IList, dobbiamo cambiare il nome per rendere più chiaro a cosa stiamo scrivendo:

Ecco come apparirebbe il codice per la funzione:

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();
}

Possiamo migliorarlo ulteriormente consentendo al client di passare nel delimitatore.Potremmo quindi fornire una seconda funzione che scriva sulla console con il delimitatore standard in questo modo:

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();
}

Quindi ora, dato che vogliamo un modo breve, chiaro e performante per scrivere elenchi sulla console, ne abbiamo uno.Ecco l'intero codice sorgente inclusa una dimostrazione dell'utilizzo della funzione di libreria:

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();
        }
    }
}

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

Potresti pensare che questa dovrebbe essere la fine della risposta.Tuttavia c’è un’ulteriore generalizzazione che può essere fatta.Dalla domanda di fatcat non è chiaro se scrive sempre alla console.Forse c'è qualcos'altro da fare in foreach.In tal caso la risposta di Jason Bunting darà quella generalità.Ecco ancora la sua risposta:

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

Questo a meno che non apportiamo un ulteriore perfezionamento ai nostri metodi di estensione e aggiungiamo FastForEach come di seguito:

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();
    }

Ciò ci consente di eseguire qualsiasi codice arbitrario su ogni elemento della raccolta utilizzando il metodo di iterazione più veloce possibile.

Possiamo anche modificare la funzione WriteToConsole per utilizzare FastForEach

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

Quindi ora l'intero codice sorgente, incluso un esempio di utilizzo di FastForEach, è:

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();
        }
    }
}

nuova lista { 1, 3, 5 }.ForEach(Console.WriteLine);

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

modificare:ahhh mi ha preceduto.

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

Modificare:Dannazione!ci è voluto troppo tempo per aprire Visual Studio per testarlo.

Inoltre puoi partecipare:

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();
}

Poi più tardi...

list.WriteLine();
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top