Question

J'ai une application console C # de base qui lit un fichier texte (format CSV) ligne par ligne et place les données dans une table de hachage. Le premier élément CSV de la ligne est la clé (id num) et le reste de la ligne est la valeur. Cependant, j'ai découvert que mon fichier d'importation contenait quelques clés dupliquées qu'il n'aurait pas dû avoir. Lorsque j'essaie d'importer le fichier, l'application génère des erreurs car vous ne pouvez pas avoir de clés dupliquées dans un HashTable. Je veux cependant que mon programme puisse gérer cette erreur. Lorsque je rencontre une clé en double, j'aimerais la placer dans un répertoire et continuer à importer le reste des données dans la table de hachage. Comment puis-je faire cela en C #

Voici mon code:

importFile statique Hashtable statique privé (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;
    }
Était-ce utile?

La solution

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

Autres conseils

Une meilleure solution consiste à appeler ContainsKey pour vérifier si la clé existe avant de l’ajouter à la table de hachage. Lancer une exception sur ce type d'erreur est un coup dur pour la performance et n'améliore pas le flux du programme.

ContainsKey a une surcharge constante de O (1) pour chaque élément, tandis que capturer une exception entraîne une baisse de performance sur JUST les éléments en double.

Dans la plupart des cas, je dirais de vérifier la clé, mais dans ce cas, il vaut mieux détecter l’exception.

Voici une solution qui évite les occurrences multiples dans la liste secondaire avec un léger surcoût pour toutes les insertions:

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

Vous pouvez envelopper le dictionnaire dans un type qui le cache ou le placer dans une méthode ou même une méthode d'extension dans le dictionnaire.

Si vous avez plus de 4 valeurs CSV (par exemple), il peut être intéressant de définir la variable valeur pour utiliser également un StringBuilder, car la concaténation de chaînes est une fonction lente.

Hmm, 1,7 million de lignes? J’hésite à proposer ceci pour ce type de charge.

Voici un moyen de faire cela en utilisant 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);
  } 
}

Merci à vous tous. J'ai fini par utiliser la méthode ContainsKey (). Cela prend peut-être 30 secondes de plus, ce qui convient à mes besoins. Je charge environ 1,7 million de lignes et le programme prend environ 7 minutes au total pour charger deux fichiers, les comparer et écrire quelques fichiers. Il ne faut que 2 secondes environ pour comparer et écrire les fichiers.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top