У меня есть базовое консольное приложение 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;
}





Лучшее решение - вызвать ContainsKey, чтобы проверить, существует ли ключ, прежде чем добавлять его в хеш-таблицу. Выдача исключения при такой ошибке снижает производительность и не улучшает выполнение программы.
if (myHashtable.ContainsKey(key))
duplicates.Add(key);
else
myHashtable.Add(key, value);
ContainsKey имеет постоянные накладные расходы O (1) для каждого элемента, в то время как перехват исключения приводит к снижению производительности ТОЛЬКО повторяющихся элементов.
В большинстве случаев я бы сказал, проверьте ключ, но в этом случае лучше поймать исключение.
Возможно, я ошибаюсь, но я почти уверен, что проверка наличия элемента в списке - O (N), но для хэша - O (1).
Вот решение, которое позволяет избежать множественных попаданий во вторичный список с небольшими накладными расходами на все вставки:
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);
Вы можете обернуть словарь в тип, который скрывает это, или поместить его в метод или даже метод расширения в словаре.
И да, я знаю, что множественные попадания во вторичный список маловероятны, но это не повредит, чтобы быть уверенным :)
Спасибо вам всем. В итоге я использовал метод ContainsKey (). На это уходит, может быть, на 30 секунд больше, что вполне подходит для моих целей. Я загружаю около 1,7 миллиона строк, а программе требуется около 7 минут, чтобы загрузить два файла, сравнить их и записать несколько файлов. Для сравнения и записи файлов требуется всего около 2 секунд.
Попробуйте использовать StringBuilder.Append вместо оператора string + и посмотрите, ускорит ли он это.
Если у вас более 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);
}
}
Название вводит в заблуждение. Можем ли мы получить редактирование заголовка?