Как правильно прочитать файл csv?
Есть класс где считывает переменные:
[Serializable]
public class Class1
{
[CsvColumn(Name = "1", FieldIndex = 1)]
public string ID { get; set; }
[CsvColumn(Name = "0", FieldIndex = 2)]
public string Parent { get; set; }
[CsvColumn(Name = "aaa", FieldIndex = 3)]
public string Text { get; set; }
}
и сама главная программа где все это выводит:
static void Main(string[] args)
{
ReadCsvFile();
Console.ReadKey();
}
private static void ReadCsvFile()
{
var csvFileDescription = new CsvFileDescription
{
FirstLineHasColumnNames = true,
IgnoreUnknownColumns = true,
SeparatorChar = ';',
UseFieldIndexForReadingData = false
};
var csvContext = new CsvContext();
var document = csvContext.Read<Class1>("Документ.csv", csvFileDescription);
foreach (var files in document)
{
if (files.Parent == "0")
Console.WriteLine($"{int.Parse(files.ID)} | {int.Parse(files.Parent)} | {files.Text.TrimStart()} ' - это корневой элемент'");
else
if (files.Parent != "0")
Console.WriteLine($"{int.Parse(files.ID)} | {int.Parse(files.Parent)} | {files.Text.TrimStart()} ' - это дочерний элемент'");
}
и есть задание, по которому я должен это сделать, в самом заголовке не поместилось - поэтому пишу здесь: В исходном наборе данных, к примеру, CSV файл, содержатся данные, разбитые по трем колонкам:
Id - идентификатор родительского элемента
Parent - ссылка на родительский элемент
Text - произвольный текст
Id; Parent; Text
Если Parent = 0 то этот элемент является корневым, в противном случае элемент у которого Parent не 0 является дочерним.
Пример корневого элемента:
5;0;aaa
Пример дочернего элемента:
2;5;жжж
Вложенность дочерних элементов произвольна, то есть, к примеру:
5;0;aaa
2;5;жжж
1;2;ббб
Первая строка (Id = 5) - корневой элемент
Вторая строка (Id = 2) - дочерний элемент первой строки
Третья строка (Id = 1) - дочерний элемент второй строки
Необходимо написать программу, которая будет выводить все элементы из предоставленного списка, в виде дерева.
Количество элементов и вложенность ветвей дерева может быть произвольной.
К пирмеру, последовательность из указанных выше строк на выходе должна получить вид:
5;0;aaa
2;5;жжж
1;2;ббб
Также, необходимо выполнить сортировку внутри каждой группы элементов.
вот сам результат того что я сделал:
я сделал только само чтение файла
но я сделал что смог подскажите как мне сделать сравнение Parent одной строки с ID в каждой строке, допустим строка где текст zead там он не входит в дерево так как Parent = 20 а ID нету с 20 номером и в следствии этого должно вывести сообщение что оно не входит в дерево и плюс сделать само дерево с отступом. Заранее спасибо за предоставленную помощь!!!
Ответы (1 шт):
Возьмем класс
public class Class1
{
public string ID { get; set; }
public string Parent { get; set; }
public string Text { get; set; }
}
заполним
var classes = new[] {
new Class1(){ID ="1", Parent = "2", Text = "t1"},
new Class1(){ID ="2", Parent = "3", Text = "t2"},
new Class1(){ID ="3", Parent = "5", Text = "t3"},
new Class1(){ID ="4", Parent = "1", Text = "t4"},
};
Добавим все айдишники в хешет
var set = new HashSet<string>();
foreach(var c in classes) set.Add(c.ID);
Выпишем классы, у которых родитель не нашёлся
foreach (var c in classes)
if (!set.Contains(c.Parent))
Console.WriteLine($"У {c.ID}-{c.Text} парент {c.Parent} не нашелся!");
Результат
У 3-t3 парент 5 не нашелся!
Теперь более сложный пример
var classes = new[] {
new Class1(){ID ="1", Parent = "2", Text = "t1"},
new Class1(){ID ="2", Parent = "4", Text = "t2"},
new Class1(){ID ="3", Parent = "15", Text = "t3"},
new Class1(){ID ="4", Parent = "0", Text = "t4"},
new Class1(){ID ="5", Parent = "4", Text = "t5"},
new Class1(){ID ="6", Parent = "4", Text = "t6"},
new Class1(){ID ="7", Parent = "4", Text = "t7"},
};
в этот раз примем, что Parent="0" означает корневой узел и добавит его сразу в хешсет
var set = new HashSet<string>();
set.Add("0");
foreach(var c in classes) set.Add(c.ID);
foreach (var c in classes)
if (!set.Contains(c.Parent)) Console.WriteLine($"У {c.ID}-{c.Text} парент {c.Parent} не нашелся!");
Далее, построим словарь, где ключ - это ид родителя, а значение - список дочерних узлов. Добавим словарь и заполним
var dict = new Dictionary<string, List<Class1>>();
foreach (var c in classes)
{
if (!dict.ContainsKey(c.Parent)) dict[c.Parent] = new List<Class1>();
dict[c.Parent].Add(c);
}
Вывод узлов сделаем самописным методом
PrintNodes(dict, "0");
Сам метод использует рекурсию. Так как в задаче говорится о дереве - значит не ожидается никаких циклов в нем, тогда рекурсивный вывод сработает. Но если будут в данных циклы - то вся программа упадет.
Если хотите разобраться, как этот метод работает - гуглите "обход дерева в глубину"
private static void PrintNodes(Dictionary<string, List<Class1>> dict, string currentParent, string tab = ""){
if (!dict.ContainsKey(currentParent)) return;
foreach (var node in dict[currentParent].OrderBy(x=>x.Text))
{
Console.WriteLine($"{tab}Node:{node.ID}, {node.Text}, Parent:{node.Parent}");
PrintNodes(dict, node.ID, tab + " ");
}
}
Вывод на консоль:
У 3-t3 парент 15 не нашелся!
Node:4, t4, Parent:0
Node:2, t2, Parent:4
Node:1, t1, Parent:2
Node:5, t5, Parent:4
Node:6, t6, Parent:4
Node:7, t7, Parent:4