Domanda

Ho un'applicazione console C # di base che legge un file di testo (formato CSV) riga per riga e inserisce i dati in una tabella hash. Il primo elemento CSV nella riga è la chiave (id num) e il resto della riga è il valore. Tuttavia ho scoperto che il mio file di importazione ha alcune chiavi duplicate che non avrebbe dovuto avere. Quando provo a importare il file, l'applicazione si guasta perché non è possibile avere chiavi duplicate in una HashTable. Voglio che il mio programma sia in grado di gestire questo errore. Quando incontro una chiave duplicata, vorrei inserire quella chiave in un array e continuare a importare il resto dei dati nella tabella hash. Come posso farlo in C #

Ecco il mio codice:


importFile Hashtable statico privato (Hashtable myHashtable, String myFileName)         {

        StreamReader sr = new StreamReader(myFileName);
        CSVReader csvReader = new CSVReader();
        ArrayList tempArray = new ArrayList();
        int count = 0;

        while (!sr.EndOfStream)
        {
            String temp = sr.ReadLine();
            if (temp.StartsWith(" "))
            {
                ServMissing.Add(temp);
            }
            else
            {
                tempArray = csvReader.CSVParser(temp);
                Boolean first = true;
                String key = "";
                String value = "";

                foreach (String x in tempArray)
                {
                    if (first)
                    {
                        key = x;
                        first = false;
                    }
                    else
                    {
                        value += x + ",";
                    }
                }
                myHashtable.Add(key, value);
            }
            count++;
        }

        Console.WriteLine("Import Count: " + count);
        return myHashtable;
    }
È stato utile?

Soluzione

if (myHashtable.ContainsKey(key))
    duplicates.Add(key);
else
    myHashtable.Add(key, value);

Altri suggerimenti

Una soluzione migliore è chiamare ContainsKey per verificare se la chiave esiste prima di aggiungerla alla tabella hash. Generare un'eccezione su questo tipo di errore è un successo in termini di prestazioni e non migliora il flusso del programma.

ContainsKey ha un overhead costante di O (1) per ogni articolo, mentre catturare un'eccezione comporta un impatto sulle prestazioni SOLO sugli oggetti duplicati.

Nella maggior parte dei casi, direi di cercare la chiave, ma in questo caso è meglio prendere l'eccezione.

Ecco una soluzione che evita più hit nell'elenco secondario con un piccolo sovraccarico a tutti gli inserimenti:

Dictionary<T, List<K>> dict = new Dictionary<T, List<K>>();

//Insert item
if (!dict.ContainsKey(key))
   dict[key] = new List<string>();
dict[key].Add(value);

Puoi racchiudere il dizionario in un tipo che lo nasconde o inserirlo in un metodo o addirittura in un metodo di estensione nel dizionario.

Se hai più di 4 (ad esempio) valori CSV, potrebbe valere la pena impostare la variabile valore per usare StringBuilder, poiché la concatenazione di stringhe è una funzione lenta.

Hmm, 1,7 milioni di linee? Esito a offrire questo per quel tipo di carico.

Ecco un modo per farlo usando LINQ.

CSVReader csvReader = new CSVReader();
List<string> source = new List<string>();
using(StreamReader sr = new StreamReader(myFileName))
{
  while (!sr.EndOfStream)
  {
    source.Add(sr.ReadLine());
  }
}
List<string> ServMissing =
  source
  .Where(s => s.StartsWith(" ")
  .ToList();
//--------------------------------------------------
List<IGrouping<string, string>> groupedSource = 
(
  from s in source
  where !s.StartsWith(" ")
  let parsed = csvReader.CSVParser(s)
  where parsed.Any()
  let first = parsed.First()
  let rest = String.Join( "," , parsed.Skip(1).ToArray())
  select new {first, rest}
)
.GroupBy(x => x.first, x => x.rest)   //GroupBy(keySelector, elementSelector)
.ToList()
//--------------------------------------------------
List<string> myExtras = new List<string>();
foreach(IGrouping<string, string> g in groupedSource)
{
  myHashTable.Add(g.Key, g.First());
  if (g.Skip(1).Any())
  {
    myExtras.Add(g.Key);
  } 
}

Grazie a tutti. Ho finito con il metodo ContainsKey (). Ci vogliono forse 30 secondi in più, il che va bene per i miei scopi. Sto caricando circa 1,7 milioni di righe e il programma impiega circa 7 minuti in totale per caricare due file, confrontarli e scrivere alcuni file. Ci vogliono solo circa 2 secondi per fare il confronto e scrivere i file.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top