Related
I'm sorry that I interrupt you in this manner, I'm new to C# and I've been struggling with this problem for days... Maybe it will seem easy for you :)
I have this text file in this format
name|ID|domain|grade|verdict
Ryan|502322|Computers|9,33|Undefined
Marcel|302112|Automatics|6,22|Undefined
Alex|301234|Computers|5,66|Undefined
Leo|201122|Automatics|3,22|Undefined
How can I sort the text file using any methods (including LINQ) so that the list from the text file will be ordered by domain, and then descending by the grade column? Like this:
name|ID|domain|grade|verdict
Marcel|302112|Automatics|6,22|Undefined
Leo|201122|Automatics|3,22|Undefined
Ryan|502322|Computers|9,33|Undefined
Alex|301234|Computers|5,66|Undefined
To read the file, I'm using var Students = File.ReadAllLines(#"filepath");, I don't know if it's the smartest approach, and then I write using File.WriteAllLines
Thanks in advance! Sorry once again, I know it should be easy, but for me is really tuff :(
You can use some thing like this:
var students= File.ReadAllLines(#"filepath");
var headers = lines[0];
students = lines.Skip(1).ToArray();
var orders = lines.Select(x => x.Split('|'))
.Select(x => new { Domain = x[2], Grade = int.Parse(x[3].Replace(",", "")), All = x })
.OrderBy(x => x.Domain).ThenByDescending(x => x.Grade).Select(x => string.Join("|", x.All)).ToList();
orders.Insert(0, headers);
students=orders.ToArray();
try following code:
private void ReadFile()
{
char Delimiter = '|';
string[] Lines = File.ReadAllLines(#"E:\RaftehHa.txt", Encoding.Default);
List<string[]> FileRows = Lines.Select(line =>
line.Split(new[] { Delimiter }, StringSplitOptions.RemoveEmptyEntries)).ToList();
DataTable dt = new DataTable();
dt.Columns.AddRange(FileRows[0].Select(col => new DataColumn() { ColumnName = col }).ToArray());
FileRows.RemoveAt(0);
FileRows.ForEach(row => dt.Rows.Add(row));
DataView dv = dt.DefaultView;
dv.Sort = " ID ASC ";
dt = dv.ToTable();
dataGridView1.DataSource = dt;
}
A bit the same as already mentioned above, but as you mention you are new to C#, I have tried to add a little bit of structure to the code, but leaving the completion to you.
public class Data
{
public Data(string inputLine)
{
var split = inputLine.Split('|');
Name = split[0];
Id = int.Parse(split[1]);
Domain = split[2];
Grade = double.Parse(split[3].Replace(",", "."));
Verdict = split[4];
}
public string Name { get; }
public int Id { get; }
public string Domain { get; }
public double Grade { get; }
public string Verdict { get; }
}
public class DataFile
{
public static IEnumerable Read(string fileName)
{
var input = File.ReadAllLines(fileName);
return input.Skip(1).Select(p => new Data(p)); // skip header
}
public static void Write(IEnumerable data)
{
// todo :)
}
}
void Main()
{
var input = DataFile.Read(#"C:\Temp\ExampleData.txt");
var result = input.OrderBy(p => p.Domain).ThenByDescending(p => p.Grade);
DataFile.Write(result);
}
using System;
using System.IO;
using System.Linq;
using System.Collections.Generic;
enum DomainType {
Automatics, // 0
Computers // 1
}
class Data {
public int Id { get; set; }
public string Name { get; set; }
public string Verdict { get; set; }
public DomainType Domain { get; set; }
public Tuple<int, int> Grade { get; set; }
}
public static class Program {
static IEnumerable<Data> FileContent(string path) {
string line;
using (var reader = File.OpenText(path))
{
bool skipHeader = false;
while((line = reader.ReadLine()) != null)
{
if (!skipHeader) {
skipHeader = true;
continue;
}
var fields = line.Split('|');
string name = fields[0];
int id = int.Parse(fields[1]);
var domain = (DomainType)Enum.Parse(typeof(DomainType), fields[2]);
var grade = Tuple.Create(int.Parse(fields[3].Split(',')[0]),
int.Parse(fields[3].Split(',')[1]));
string verdict = fields[4];
var data = new Data() {
Name = name, Id = id, Domain = domain, Grade = grade, Verdict = verdict };
yield return data;
}
}
}
public static void Main() {
var result = FileContent("path_to_file").OrderBy(data => data.Domain);
foreach (var line in result) {
Console.WriteLine(line.Name);
}
}
}
I'm trying to parse the text file but unable to parse the contents under "Columns:", "Records:", "Relationships:" headings.
My text file format:
Database
Type: SQL Server
Connection String:Server=localhost\SQLEXPRESS;Database=master;Trusted_Connection=True;
DBName:FirstDataBase
Tables
Table
Name:TableName1
Columns:
ID,numeric,4
Name,name,20
Designation,varchar,20
Relationships:
Records:
9001,XYZ,Director
8038,MNO,Associate
9876,LOP,HR
Table
Name:TableName2
Columns:
ID,numeric,4
Name,name,20
Designation,varchar,20
Relationships:
TableName1,TableName2,FK,ID
Records:
8038,MNO,Associate
My C# code:
static void Main(string[] args)
{
Console.WriteLine("Enter file name");
string filep = Console.ReadLine();
string filePath = $"C:\\Files\\{filep}.txt";
List<Columns> col = new List<Columns>();
List<TableName> tn = new List<TableName>();
string[] lines = File.ReadAllLines(filePath);
foreach (var line in lines)
{
if (line.StartsWith("\t" + "\t" + "Name:"))
{
TableName newTN = new TableName();
string s = line.Split(':')[1];
newTN.TName = s;
tn.Add(newTN);
Console.WriteLine(s);
}
if (line.StartsWith("\t" + "\t" + "Columns:"))
{
// Here I'm stuck
}
}
}
One of my model classes:
public class Columns
{
public string CName { get; set; }
public string CType { get; set; }
public string CSize { get; set; }
public string Ckey { get; set; }
}
I've tried various codes but still, I'm unable to parse it. Solutions are welcome and thanks in advance.
I'm stuck at how to make the program read the next lines of particular heading and store it in a list. If it is solved then I can easily make queries and connect to the database.
Try following :
sing System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
namespace ConsoleApp1
{
class Program
{
const string FILENAME = #"c:\temp\test.txt";
static void Main(string[] args)
{
Database database = new Database(FILENAME);
}
}
public enum STATE
{
GET_DATABASE,
GET_TABLES
}
public enum TABLE_FIELD
{
NONE,
NAME,
COLUMNS,
RELATIONSHIPS,
RECORDS
}
public class Database
{
public string type { get; set; }
public string connection { get; set; }
public string name { get; set; }
public List<Table> tables { get; set; }
public Database(string filename)
{
StreamReader reader = new StreamReader(filename);
string line = "";
STATE state = STATE.GET_DATABASE;
TABLE_FIELD tableField = TABLE_FIELD.NONE;
Table table = null;
string[] splitLine;
while((line = reader.ReadLine()) != null)
{
line = line.Trim();
if (line.Length > 0)
{
switch (state)
{
case STATE.GET_DATABASE:
if (line == "Tables")
{
state = STATE.GET_TABLES;
}
else
{
if (line.Contains(":"))
{
splitLine = line.Split(new char[] { ':' });
switch (splitLine[0])
{
case "Type":
type = splitLine[1].Trim();
break;
case "Connection String":
connection = splitLine[1].Trim();
break;
case "DBName":
name = splitLine[1].Trim();
break;
}
}
}
break;
case STATE.GET_TABLES:
if(line == "Table")
{
if (tables == null) tables = new List<Table>();
table = new Table();
tables.Add(table);
}
else
{
if (line.Contains(":"))
{
splitLine = line.Split(new char[] { ':' });
switch (splitLine[0])
{
case "Name":
table.name = splitLine[1].Trim();
tableField = TABLE_FIELD.NAME;
break;
case "Columns":
connection = splitLine[1].Trim();
tableField = TABLE_FIELD.COLUMNS;
break;
case "Relationships":
name = splitLine[1].Trim();
tableField = TABLE_FIELD.RELATIONSHIPS;
break;
case "Records":
name = splitLine[1].Trim();
tableField = TABLE_FIELD.RECORDS;
break;
}
}
else
{
switch (tableField)
{
case TABLE_FIELD.COLUMNS:
if (table.columns == null) table.columns = new List<Column>();
Column column = new Column();
table.columns.Add(column);
splitLine = line.Split(new char[] { ',' });
column.name = splitLine[0];
column.type = (COLUMN_TYPE)Enum.Parse(typeof(COLUMN_TYPE), splitLine[1]);
column.length = int.Parse(splitLine[2]);
break;
case TABLE_FIELD.RECORDS:
splitLine = line.Split(new char[] { ',' });
if (table.records == null) table.records = new List<List<object>>();
List<object> row = new List<object>();
table.records.Add(row);
for(int i = 0; i < splitLine.Length; i++)
{
switch(table.columns[i].type)
{
case COLUMN_TYPE.numeric:
row.Add(int.Parse(splitLine[i]));
break;
case COLUMN_TYPE.name:
row.Add(splitLine[i]);
break;
case COLUMN_TYPE.varchar:
row.Add(splitLine[i]);
break;
}
}
break;
default:
break;
}
}
}
break;
}
}
}
}
}
public class Table
{
public string name { get; set; }
public List<Column> columns { get; set; }
public List<Relationship> relationships { get; set; }
public List<List<object>> records { get; set; }
}
public enum COLUMN_TYPE
{
numeric,
name,
varchar
}
public class Column
{
public string name { get; set; }
public COLUMN_TYPE type { get; set; }
public int length { get; set; }
}
public class Relationship
{
}
}
Starting from a table of daily fruit prices
fruits.csv
Day,Name,Kind,Price
2019-09-04,"apple","red",63.09
2019-09-04,"apple","yellow",52.14
2019-09-04,"orange","navel",41.18
2019-09-04,"orange","blood",41.18
2019-09-03,"apple","red",63.07
2019-09-03,"apple","yellow",52.11
2019-09-03,"orange","navel",41.13
2019-09-03,"orange","blood",41.13
I'd like to insert the reference prices by name and kind
fruit_ref_prices.csv
Name,Kind,Reference_Price
"apple","red",60.00
"apple","yellow",50.00
"orange","navel",40.00
"orange","blood",42.00
to result in the following table
Day,Name,Kind,Price,Reference_Price
2019-09-04,"apple","red",63.09,60.00
2019-09-04,"apple","yellow",52.14,50.00
2019-09-04,"orange","navel",41.18,40.00
2019-09-04,"orange","blood",41.18,42.00
2019-09-03,"apple","red",63.07,60.00
2019-09-03,"apple","yellow",52.11,50.00
2019-09-03,"orange","navel",41.13,40.00
2019-09-03,"orange","blood",41.13,42.00
The solution should be simple using C#'s built-in SQL-like syntax, and I'm sure the answer lies in one of the following tutorial pages:
Join clause
Perform custom join operations
Join by using composite keys
but I'm having a hard time identifying the syntax of this language.
In my attempt below instead of writing
join fruit_ref in fruit_refs on fruit.name equals fruit_ref.name
I should be able to write
join fruit_ref in fruit_refs on fruit.name equals fruit_ref.name
and fruit.kind equals fruit_ref.kind
but the Boolean expression is not accepted. Why?
My attempt is:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using System.IO;
namespace MyConsoleApplication
{
class Program
{
const string root = #"c:\path\to\here\";
const string file1_in = root + #"fruits.csv";
const string file2_in = root + #"fruit_ref_prices.csv";
static void Main(string[] args)
{
Fruit_Basket fruit_basket = new Fruit_Basket(file1_in, file2_in);
fruit_basket.PrintFruits();
}
}
public class Fruit
{
public DateTime day { get; set; }
public string name { get; set; }
public string kind { get; set; }
public decimal price { get; set; }
public Fruit(DateTime newFruit_day,
string newFruit_name,
string newFruit_kind,
decimal newFruit_price)
{
this.day = newFruit_day;
this.name = newFruit_name;
this.kind = newFruit_kind;
this.price = newFruit_price;
}
}
public class Fruit_Ref
{
public string name;
public string kind;
public decimal reference_price;
public Fruit_Ref(string newName, string newKind, decimal newRef_Price)
{
this.name = newName;
this.kind = newKind;
this.reference_price = newRef_Price;
}
}
public class Fruit_Basket {
public List<Fruit> fruits { get; set; }
public List<Fruit_Ref> fruit_refs { get; set; }
public Fruit_Basket(string file1_in, string file2_in) {
build_fruit_list(file1_in);
build_fruit_ref_list(file2_in);
}
public void build_fruit_list(string file_in)
{
fruits = new List<Fruit>();
int count = 0;
StreamReader reader = new StreamReader(file_in);
string line = "";
while ((line = reader.ReadLine()) != null)
{
if (++count > 1)
{
string[] splitLine = line.Split(new char[] { ',' }).ToArray();
var newFruit_day = DateTime.Parse(splitLine[0]);
var newFruit_name = splitLine[1];
var newFruit_kind = splitLine[2];
var newFruit_price = decimal.Parse(splitLine[3]);
Fruit newFruit = new Fruit(newFruit_day,
newFruit_name,
newFruit_kind,
newFruit_price);
fruits.Add(newFruit);
}
}
reader.Close();
}
public void build_fruit_ref_list(string file_in)
{
fruit_refs = new List<Fruit_Ref>();
int count = 0;
StreamReader reader = new StreamReader(file_in);
string line = "";
while ((line = reader.ReadLine()) != null)
{
if (++count > 1)
{
string[] splitLine = line.Split(new char[] { ',' }).ToArray();
var newFruit_name = splitLine[0];
var newFruit_kind = splitLine[1];
var newFruit_ref_price = decimal.Parse(splitLine[2]);
Fruit_Ref newFruit_ref = new Fruit_Ref(newFruit_name,
newFruit_kind,
newFruit_ref_price);
fruit_refs.Add(newFruit_ref);
}
}
reader.Close();
}
public void PrintFruits()
{
var innerJoinQuery =
from fruit in fruits
join fruit_ref in fruit_refs on fruit.name equals fruit_ref.name
select new { Day = fruit.day, Name = fruit.name, Kind = fruit.kind,
Price = fruit.price, Reference_Price = fruit_ref.reference_price };
Console.WriteLine($#"""Date"",""Name"",""Kind"",""Price"",""Ref Price""");
foreach (var i in innerJoinQuery)
{
Console.WriteLine($#"{i.Day},{i.Kind},{i.Price},{i.Reference_Price}");
}
}
}
}
You could also refactor your code to use the CsvHelper NuGet package for reading/writing CSV files.
First, You can make these classes to reflect the fruits, fruit references and final fruit structure.
public class Fruit
{
public string Day { get; set; }
public string Name { get; set; }
public string Kind { get; set; }
public string Price { get; set; }
}
public class FruitReferencePrice
{
public string Name { get; set; }
public string Kind { get; set; }
public string Reference_Price { get; set; }
}
public class FruitFinal
{
public string Day { get; set; }
public string Name { get; set; }
public string Kind { get; set; }
public string Price { get; set; }
public string ReferencePrice { get; set; }
public override string ToString()
{
return $"Day={Day},Name={Name},Kind={Kind},Price={Price},Reference_Price={ReferencePrice}";
}
}
Then you can make two methods to return the rows of each CSV file into List<Fruit> and List<FruitReferencePrice>.
private static IEnumerable<Fruit> BuildFruitList(string csvFilePath)
{
if (!File.Exists(csvFilePath))
{
throw new FileNotFoundException("Could not locate CSV at path " + csvFilePath, csvFilePath);
}
try
{
using var fileReader = File.OpenText(csvFilePath);
using var csv = new CsvReader(fileReader);
return csv.GetRecords<Fruit>().ToList();
} catch (Exception ex)
{
Console.WriteLine(ex.Message);
return Enumerable.Empty<Fruit>();
}
}
private static IEnumerable<FruitReferencePrice> BuildFruitReferenceList(string csvFilePath)
{
if (!File.Exists(csvFilePath))
{
throw new FileNotFoundException("Could not locate CSV at path " + csvFilePath, csvFilePath);
}
try
{
using var fileReader = File.OpenText(csvFilePath);
using var csv = new CsvReader(fileReader);
return csv.GetRecords<FruitReferencePrice>().ToList();
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
return Enumerable.Empty<FruitReferencePrice>();
}
}
Then you can perform a grouped join and output the merged result.
var path1 = "PATH\\fruits.csv";
var path2 = "PATH\\fruit_ref_prices.csv";
var fruitList = BuildFruitList(path1);
var fruitReferencePrices = BuildFruitReferenceList(path2);
var groupedJoin = from fruit in fruitList
join fruit_ref in fruitReferencePrices
on new { fruit.Name, fruit.Kind } equals new { fruit_ref.Name, fruit_ref.Kind }
select new FruitFinal
{
Day = fruit.Day,
Name = fruit.Name,
Kind = fruit.Kind,
Price = fruit.Price,
ReferencePrice = fruit_ref.Reference_Price
};
foreach (var fruit in groupedJoin)
{
Console.WriteLine(fruit.ToString());
}
Merged results:
Day=2019-09-04,Name=apple,Kind=red,Price=63.09,Reference_Price=60.00
Day=2019-09-04,Name=apple,Kind=yellow,Price=52.14,Reference_Price=50.00
Day=2019-09-04,Name=orange,Kind=navel,Price=41.18,Reference_Price=40.00
Day=2019-09-04,Name=orange,Kind=blood,Price=41.18,Reference_Price=42.00
Day=2019-09-03,Name=apple,Kind=red,Price=63.07,Reference_Price=60.00
Day=2019-09-03,Name=apple,Kind=yellow,Price=52.11,Reference_Price=50.00
Day=2019-09-03,Name=orange,Kind=navel,Price=41.13,Reference_Price=40.00
Day=2019-09-03,Name=orange,Kind=blood,Price=41.13,Reference_Price=42.00
Please change the equals clause as on new { fruit.name, fruit.kind } equals new { fruit_ref.name, fruit_ref.kind }
Why you require this
The query has two anonymous types (one for left table and one for right table). So to compare those anonymous types, the linq statement should use new keyword
Query :
var innerJoinQuery = from fruit in fruits
join fruit_ref in fruit_refs on new { fruit.name, fruit.kind } equals new { fruit_ref.name, fruit_ref.kind }
select new { Day = fruit.day, Name = fruit.name, Kind = fruit.kind,
Price = fruit.price, Reference_Price = fruit_ref.reference_price };
Say we want to calculate how the price of some fruits are changing. Starting from a CSV file:
Day,Name,Kind,Price
2019-09-04,"apple","red delicious",63.09
2019-09-04,"apple","ginger crisp",52.14
2019-09-04,"orange","navel",41.18
2019-09-03,"apple","red delicious",63.07
2019-09-03,"apple","ginger crisp",52.11
2019-09-03,"orange","navel",41.13
2019-09-02,"apple","red delicious",63.00
2019-09-02,"apple","ginger crisp",52.00
2019-09-02,"orange","navel",41.00
with an unknown number of fruits and varieties, we can read the dataframe and build an extra column to use for matching.
var fruits_file = Path.Combine(root, "fruits.csv");
Deedle.Frame<int, string> df = Frame.ReadCsv(fruits_file);
Series<int, string> name = df.GetColumn<string>("Name");
Series<int, string> kind = df.GetColumn<string>("Kind");
var namekind = name.ZipInner(kind).Select(t => t.Value.Item1 + t.Value.Item2);
df.AddColumn("NameKind", namekind);
but the problem remains. Deedle.Series.Window() and Deedle.Series.Pairwise() make it possible to perform first-order differences, but not matching based on some string (namekind).
What is the right way to copy over a column LastPrice and subsequently calculate the Change?
Day,Name,Kind,Price,LastPrice,Change
2019-09-04,"apple","red delicious",63.09,63.07,0.02
2019-09-04,"apple","ginger crisp",52.14,52.11,0.03
2019-09-04,"orange","navel",41.18,41.13,0.05
2019-09-03,"apple","red delicious",63.07,63.00,0.07
2019-09-03,"apple","ginger crisp",52.11,52.00,0.11
2019-09-03,"orange","navel",41.13,41.00,0.13
2019-09-02,"apple","red delicious",63.00,,
2019-09-02,"apple","ginger crisp",52.00,,
2019-09-02,"orange","navel",41.00,,
See code below :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using System.IO;
namespace ConsoleApplication137
{
class Program
{
const string FILENAME = #"c:\temp\test.csv";
static void Main(string[] args)
{
Fruit fruit = new Fruit(FILENAME);
Fruit.PrintFruits();
Console.ReadLine();
}
}
public class Fruit
{
public static List<Fruit> fruits { get; set; }
public DateTime day { get; set; }
public string name { get; set; }
public string kind { get; set; }
public decimal price { get; set; }
public Fruit() { }
public Fruit(string filename)
{
int count = 0;
StreamReader reader = new StreamReader(filename);
string line = "";
while ((line = reader.ReadLine()) != null)
{
if (++count > 1)
{
string[] splitLine = line.Split(new char[] { ',' }).ToArray();
Fruit newFruit = new Fruit();
if (fruits == null) fruits = new List<Fruit>();
fruits.Add(newFruit);
newFruit.day = DateTime.Parse(splitLine[0]);
newFruit.name = splitLine[1];
newFruit.kind = splitLine[2];
newFruit.price = decimal.Parse(splitLine[3]);
}
}
reader.Close();
}
public static void PrintFruits()
{
var groups = fruits.OrderBy(x => x.day)
.GroupBy(x => new { name = x.name, kind = x.kind })
.ToList();
foreach (var group in groups)
{
for (int i = 0; i < group.Count() - 1; i++)
{
Console.WriteLine("Old Date : '{0}', New Date : '{1}', Name : '{2}', Kind : '{3}', Old Price '{4}', New Price '{5}', Delta Price '{6}'",
group.ToList()[i].day.ToString("yyyy-MM-dd"),
group.ToList()[i + 1].day.ToString("yyyy-MM-dd"),
group.ToList()[i].name,
group.ToList()[i].kind,
group.ToList()[i].price.ToString(),
group.ToList()[i + 1].price.ToString(),
(group.ToList()[i + 1].price - group.ToList()[i].price).ToString()
);
}
}
}
}
}
I have the following list of ContentData objects (see below the class structure):
Name = "Path1\\Path2\\Path3\\File0", Size = 110
Name = "Path1\\Path2\\Path4\\File1", Size = 112
Name = "Path1\\Path2\\Path4\\File2", Size = 22222
Name = "Path1\\Path5\\File3", Size = 2312313
Name = "Path6", Size = 0
I want to build a tree which should look like:
Path1
-> Path2
-> Path3
-> File0
-> Path4
-> File1
-> File2
-> Path5
-> File3
Path6
I tried:
public static IEnumerable<TreeDataModel> GetTree(this IEnumerable<ContentData> dataList, Func<ContentData, string> nameSelector, string root = null)
{
var enumerable = root != null ? dataList.Where(data => nameSelector(data).Equals(root)) : dataList;
foreach (var data in enumerable)
{
var split = data.Name.Split('\\');
if (split.Length > 1)
{
yield return new TreeDataModel(split[0], "", dataList.GetTree(nameSelector, string.Join("\\", split.Skip(1))));
}
else
{
yield return new TreeDataModel(split[0], "", null);
}
}
}
and ContentData contains
public string Name { get; set; }
public long Size { get; set; }
and TreeDataModel
public sealed class TreeDataModel
{
public TreeDataModel(string title, string path, IEnumerable<TreeDataModel> children)
{
Title = title;
Path = path;
Children = children;
}
public string Title { get; }
public string Path { get; }
public IEnumerable<TreeDataModel> Children { get; }
}
I'm stucked at extension and I don't know how to achieve the results.
Means that the results I got now is that appears multiple times same first part before \
Try code like below :
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace WindowsFormsApplication54
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
List<ContentData> data = new List<ContentData>() {
new ContentData("Path1\\Path2\\Path3\\File0", 110),
new ContentData("Path1\\Path2\\Path4\\File1", 112),
new ContentData("Path1\\Path2\\Path4\\File2", 22222),
new ContentData("Path1\\Path5\\File3", 2312313),
new ContentData("Path6", 0)
};
CreateTreeRecursive(data, null, 0);
treeView1.ExpandAll();
}
public void CreateTreeRecursive(List<ContentData> data, TreeNode node, int index)
{
var groupData = data.Where(x => x.splitName.Length > index).GroupBy(x => x.splitName[index]).ToList();
foreach (var group in groupData)
{
TreeNode newNode = new TreeNode(group.Key);
if (node == null)
{
treeView1.Nodes.Add(newNode);
}
else
{
node.Nodes.Add(newNode);
}
CreateTreeRecursive(group.ToList(), newNode, index + 1);
}
}
}
public class ContentData
{
public string Name { get; set; }
public string[] splitName { get; set; }
public int Size { get; set; }
public ContentData(string name, int size)
{
Name = name;
Size = size;
splitName = name.Split(new char[] {'\\'}).ToArray();
}
}
}