Inizializzazione condizionale di una lista di stringhe

4

Sto scrivendo un programma che deve essere in grado di elaborare i dati da diverse fonti diverse. Le fonti generano dati in una varietà di formati. Quindi, a seconda di quale fonte viene utilizzata, ho bisogno di inizializzare una lista di stringhe con un diverso set di intestazioni di colonna. La quantità di intestazioni varia tra 10 e 18 colonne in base all'origine dati.

Essenzialmente, ho bisogno di un metodo pulito per inizializzare in modo condizionale un elenco. Ho tre soluzioni funzionanti, ma non sono sicuro di quale sia la migliore / migliore pratica:

  • L'Esempio n. 1 richiede che aggiungo ogni intestazione alla lista riga per riga. Con il numero di potenziali fonti e colonne che devono essere aggiunte per ciascuna, questa lista diventa piuttosto lunga.
  • L'Esempio # 2 richiede che io uso {} attorno ad ogni dichiarazione di caso per limitare l'ambito in modo che io possa dichiarare l'elenco dataHeaders individualmente in ogni dichiarazione di caso. Non ho mai incontrato una situazione in cui ho dovuto limitare la portata a una singola dichiarazione di un caso e, come tale, sospetto che sia una cattiva pratica.
  • L'esempio # 3 sembra l'opzione migliore. In realtà ho implementato questo mentre stavo scrivendo questa domanda. Non vedo davvero alcun inconveniente, ma ho pensato che avrei comunque posto la domanda comunque.

C'è un modo migliore / più pulito per fare questo? In caso negativo, quale esempio è la migliore pratica?

Esempio 1:

List<string> headers = new List<string>();
switch (dataSource)
{
    case "Source 1":
        headers.Add("header1");
        headers.Add("header2");
        headers.Add("header3");
        headers.Add("...");
        headers.Add("header18");
        break;
    case "Source 2":
        headers.Add("headerA");
        headers.Add("headerB");
        headers.Add("headerC");
        headers.Add("...");
        headers.Add("headerJ");
        break;
    default:
        // TODO: Handle bad sources.
        break;
}

Esempio n. 2:

List<string> headers = new List<string>();
switch (dataSource)
{
    case "Source 1":
        {
            List<string> dataHeaders = new List<string>() { "header1", "header2", "header3", "...", "header18" }
            headers = dataHeaders;
            break;
        }
    case "Source 2":
        {
            List<string> dataHeaders = new List<string>() { "headerA", "headerB", "headerC", "...", "headerJ" }
            headers = dataHeaders;
            break;
        }
    default:
        {
            // TODO: Handle bad sources.
            break;
        }
}

Esempio n. 3:

List<string> headers = new List<string>();
switch (dataSource)
{
    case "Source 1":
        headers.AddRange(new List<string>() { "header1", "header2", "header3", "...", "header18" })
        break;
    case "Source 2":
        headers.AddRange(new List<string>() { "headerA", "headerB", "headerC", "...", "headerJ" })
        break;
    default:
        // TODO: Handle bad sources.
        break;
}
    
posta TestEngineer 27.05.2016 - 02:30
fonte

6 risposte

3

Un sacco di volte, puoi davvero risolvere un problema come questo, esprimendo i tuoi dati in un formato con meno sintassi di un linguaggio di programmazione, come una stringa CSV. Non conosco C #, ma un esempio in Scala è:

def headersForDataSource(dataSource: String): Option[Array[String]] = {
  val headers = """
    Source1,header1,header2,header3,...,header18
    Source2,headerA,headerB,headerC,...,headerJ
    """

  val lines = headers.lines map (_.trim split ',')
  lines find (_(0) == dataSource) map (_.tail)
}

Puoi vedere che questo rende la tua lista di intestazioni molto più compatta e più facile da leggere, perché non ingombra e la mescola con la sintassi della struttura dei dati. Lo sta inserendo nel formato preferito, invece del formato forzato su di te dal linguaggio di programmazione.

    
risposta data 27.05.2016 - 05:56
fonte
1

Qual è il problema che stai tentando di risolvere?

Se stai cercando di migliorare le prestazioni, questo è sicuramente un caso di ottimizzazione prematura. Ognuno dei tre metodi che fornisci potrebbe riempire un elenco di migliaia di elementi nella frazione di un secondo necessario per sollevare il dito dal mouse dopo aver fatto clic su un pulsante.

Se stai solo cercando di rendere il tuo codice meno dettagliato, una variante dell'opzione 3 è la migliore.

var headers = new List<string>();
switch (dataSource)
{
    case "Source 1":
        headers.AddRange(new [] { "header1", "header2", "header3", "...", "header18" })
        break;
    case "Source 2":
        headers.AddRange(new [] { "headerA", "headerB", "headerC", "...", "headerJ" })
        break;
    default:
        // TODO: Handle bad sources.
        break;
}

Si noti che non è necessario specificare il tipo di elenco o le matrici per gli elementi: questi verranno automaticamente dedotti dal compilatore.

    
risposta data 27.05.2016 - 13:48
fonte
1

Puoi anche evitare switch e if usando maps . Userò la sintassi Java, ma suppongo che si possa fare facilmente in C #

Descrittore non modificabile (statico o costante)

Map<String,String[]> HEADERS_MAP = new HashMap<String,String[]>();
HEADERS_MAP.put("Source 1",new String[]{"header1","headerN"});
HEADERS_MAP.put("Source 2",new String[]{"headerA","headerZ"});
...
//Preventing Map from changes
HEADERS_MAP = Collections.unmodifiableMap(HEADERS_MAP);

Nota: penso che le mappe siano Dictorinary in C #

Generatore di intestazione

//Each consumer will have it's onw list
return Arrays.asList(HEADERS_MAP.get(dataSource));

Modifica : Ho modificato per prima risposta il commento di @ unholysampler

Ora Mappa memorizza String [] e builder restituisce un nuovo elenco nuovo / non associato. Quindi il consumatore del costruttore sarà in grado di modificare il contenuto dell'elenco e impedirà il codice da modifiche indesiderate. Potrebbe essere fatto con Collections.unmodificableList , ma in questo modo aggiunge un po 'più di codice e complessità. Fa codice meno leggibile.

    
risposta data 27.05.2016 - 08:49
fonte
0

Penso che un'opzione leggermente modificata 2 sia la soluzione migliore. Lascia la dichiarazione delle intestazioni al di fuori dell'interruttore e all'interno dell'interruttore basta impostare le intestazioni = nuova lista

Inoltre non hai bisogno delle parentesi graffe per creare blocchi per ogni dichiarazione di caso; C # ti costringerà ad avere un'interruzione alla fine di ogni caso.

Il vantaggio di fare questo è che se aggiungi un nuovo caso, sarai avvisato che le intestazioni non sono inizializzate se provi ad usarlo più tardi, dove il tuo attuale numero 2 finirà con una lista vuota , che potrebbe essere un errore logico da rintracciare più tardi.

    
risposta data 27.05.2016 - 04:00
fonte
0

Ecco una versione più breve, che combina i suggerimenti di Peregrine e Karl Bielefeldt:

string hline;
switch (dataSource)
{
    case "Source 1":
        hline = "header1,header2,header3,...,header18";
        break;
    case "Source 2":
        hline = "headerA,headerB,headerC,...,headerZ";
        break;
    default:
        // TODO: Handle bad sources.
        break;
}
var headers = new List<string>();
headers.AddRange(hline.Split(','));

Se puoi fare riferimento alle tue diverse origini dati per un indice da un intervallo consecutivo, vorrei considerare di evitare l'intero caso-switch e inizializzare hline in questo modo:

 string hLine = new []{
   "header1,header2,header3,...,header18",
   "headerA,headerB,headerC,...,headerZ",
   "..."}[dataSourceIndex];
    
risposta data 27.05.2016 - 15:30
fonte
0

Perché non usare un dizionario?

var headers = new List<string>();
var headersToAdd = new Dictionary<string, string[]>
{
    {"Source 1", new string[] {"header1", "header2"} },
    {"Source 2", new string[] {"headerA", "headerB"} }
};

headers.AddRange(headersToAdd["Source 1"]);
headers.AddRange(headersToAdd["Source 2"]);
    
risposta data 08.09.2017 - 08:22
fonte

Leggi altre domande sui tag