Продолжение обработки исключений C# при ошибке

У меня есть базовое консольное приложение C#, которое построчно читает текстовый файл (формат CSV) и помещает данные в HashTable. Первый элемент CSV в строке - это ключ (id num), а остальная часть строки - это значение. Однако я обнаружил, что в моем файле импорта есть несколько повторяющихся ключей, которых у него не должно быть. Когда я пытаюсь импортировать файл, приложение выдает ошибку, потому что у вас не может быть повторяющихся ключей в HashTable. Я хочу, чтобы моя программа могла обрабатывать эту ошибку. Когда я сталкиваюсь с повторяющимся ключом, я хотел бы поместить этот ключ в Arraylist и продолжить импорт остальных данных в хеш-таблицу. Как я могу сделать это на C#

Вот мой код:


частная статическая Hashtable importFile (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;
    }

Название вводит в заблуждение. Можем ли мы получить редактирование заголовка?

Amy B 25.09.2008 21:43
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
2
1
2 789
7
Перейти к ответу Данный вопрос помечен как решенный

Ответы 7

Лучшее решение - вызвать ContainsKey, чтобы проверить, существует ли ключ, прежде чем добавлять его в хеш-таблицу. Выдача исключения при такой ошибке снижает производительность и не улучшает выполнение программы.

Ответ принят как подходящий

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

ContainsKey имеет постоянные накладные расходы O (1) для каждого элемента, в то время как перехват исключения приводит к снижению производительности ТОЛЬКО повторяющихся элементов.

В большинстве случаев я бы сказал, проверьте ключ, но в этом случае лучше поймать исключение.

Возможно, я ошибаюсь, но я почти уверен, что проверка наличия элемента в списке - O (N), но для хэша - O (1).

Matt 25.09.2008 20:30

Вот решение, которое позволяет избежать множественных попаданий во вторичный список с небольшими накладными расходами на все вставки:

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

Вы можете обернуть словарь в тип, который скрывает это, или поместить его в метод или даже метод расширения в словаре.

И да, я знаю, что множественные попадания во вторичный список маловероятны, но это не повредит, чтобы быть уверенным :)

Morten Christiansen 25.09.2008 20:43

Спасибо вам всем. В итоге я использовал метод ContainsKey (). На это уходит, может быть, на 30 секунд больше, что вполне подходит для моих целей. Я загружаю около 1,7 миллиона строк, а программе требуется около 7 минут, чтобы загрузить два файла, сравнить их и записать несколько файлов. Для сравнения и записи файлов требуется всего около 2 секунд.

Попробуйте использовать StringBuilder.Append вместо оператора string + и посмотрите, ускорит ли он это.

jop 25.09.2008 21:20

Если у вас более 4 (например) значений CSV, возможно, стоит установить переменную ценить для использования StringBuilder, поскольку конкатенация строк - медленная функция.

Хм, 1,7 миллиона строк? Я не решаюсь предлагать это для такой нагрузки.

Вот один из способов сделать это с помощью 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);
  } 
}

Другие вопросы по теме