Making Hierarchical dictionary in c# - c#
I want to build a hierarchical dictionary structure in C# from an Excel data sheet. The structure should look like this:
{
"Data": {
survey_id: {
"SurveyParameter": {},
"SurveySetting": {},
"Boreholes": {
borehole_id: {
"BoreholeParameter": {},
"BoreholeSetting": {},
"Layers": {
"Geology": {
layer_id: {"Parameter": {}, "LayerSetting": {}}
},
"Contamination": {
layer_id: {"Parameter": {}, "LayerSetting": {}}
},
},
}
},
}
}
}
"""
An example image of Excel data sheet from which the dictionary structure is to be built is provided here:
image of excel_data
I have built a dictionary structure that looks like this second image (below). But I want to convert it to the hierarchical structure, shown at the top.
image of the built dictionary
here is the text format of the dictionary saved as json file:
"3": {
"(SurveyParameter, SurveyId)": "[Company-Year]",
"(SurveyParameter, SurveyLink)": null,
"(SurveySetting, CoordinateSystem)": "[UTM, Revit]",
"(BoreholeParameter, BoreholeId)": null,
"(BoreholeSetting, AllowOverwrite)": "[True / False (default)]",
"(BoreholeSetting, Easting)": "[m] (X-Coordinate)",
"(BoreholeSetting, Northing)": "[m] (Y-Coordinate)",
"(BoreholeSetting, Elevation)": "[m] (Z-Coordinate)",
"(BoreholeParameter, BoreholeDiameter)": "[m] (default 0.4 m)",
"(Parameter, LayerId)": null,
"(Parameter, InputLayerStartDepth)": "(automatically filled)",
"(Parameter, InputLayerEndDepth)": "[m] (relative to coordinate)",
"(LayerSetting, SoilType)": "(pre-defined)",
"(Parameter, HomogeneousAreaSoil)": "(pre-defined)",
"(Parameter, SoilDescription)": null
},
"4": {
"(SurveyParameter, SurveyId)": "BRE-18",
"(SurveyParameter, SurveyLink)": null,
"(SurveySetting, CoordinateSystem)": "UTM",
"(BoreholeParameter, BoreholeId)": "RKS A5",
"(BoreholeSetting, AllowOverwrite)": null,
"(BoreholeSetting, Easting)": 795561.0,
"(BoreholeSetting, Northing)": 2278972.0,
"(BoreholeSetting, Elevation)": null,
"(BoreholeParameter, BoreholeDiameter)": null,
"(Parameter, LayerId)": "RKS A5_1",
"(Parameter, InputLayerStartDepth)": null,
"(Parameter, InputLayerEndDepth)": 1.7,
"(LayerSetting, SoilType)": "A",
"(Parameter, HomogeneousAreaSoil)": "A",
"(Parameter, SoilDescription)": "G, s, u'"
},
"5": {
"(SurveyParameter, SurveyId)": "BRE-18",
"(SurveyParameter, SurveyLink)": null,
"(SurveySetting, CoordinateSystem)": "UTM",
"(BoreholeParameter, BoreholeId)": "RKS A5",
"(BoreholeSetting, AllowOverwrite)": null,
"(BoreholeSetting, Easting)": 795561.0,
"(BoreholeSetting, Northing)": 2278972.0,
"(BoreholeSetting, Elevation)": null,
"(BoreholeParameter, BoreholeDiameter)": null,
"(Parameter, LayerId)": "RKS A5_2",
"(Parameter, InputLayerStartDepth)": null,
"(Parameter, InputLayerEndDepth)": 2.2,
"(LayerSetting, SoilType)": "A",
"(Parameter, HomogeneousAreaSoil)": "A",
"(Parameter, SoilDescription)": "G, s, u'"
},
"6": {
"(SurveyParameter, SurveyId)": "BRE-18",
"(SurveyParameter, SurveyLink)": null,
"(SurveySetting, CoordinateSystem)": "UTM",
"(BoreholeParameter, BoreholeId)": "RKS A5",
"(BoreholeSetting, AllowOverwrite)": null,
"(BoreholeSetting, Easting)": 795561.0,
"(BoreholeSetting, Northing)": 2278972.0,
"(BoreholeSetting, Elevation)": null,
"(BoreholeParameter, BoreholeDiameter)": null,
"(Parameter, LayerId)": "RKS A5_3",
"(Parameter, InputLayerStartDepth)": null,
"(Parameter, InputLayerEndDepth)": 2.3,
"(LayerSetting, SoilType)": "Bohrhindernis",
"(Parameter, HomogeneousAreaSoil)": "Bohrhindernis",
"(Parameter, SoilDescription)": "Bohrhindernis"
I used the following code to build the dictionary in second image:
public void ExcelReader(string path)
{
var stream = File.Open(path, FileMode.Open, FileAccess.Read);
var reader = ExcelReaderFactory.CreateReader(stream);
var result = reader.AsDataSet();
var tables = result.Tables.Cast<DataTable>();
Dictionary<string,Dictionary<(object, object), object>> rows = new Dictionary<string,Dictionary<(object, object), object>> ();
foreach (DataTable table in tables)
{
//DataRow selectedRow = table.Rows[3];
//DataRow newRow = table.NewRow();
//newRow.ItemArray = selectedRow.ItemArray; // copy data
//table.Rows.Remove(selectedRow);
//table.Rows.InsertAt(newRow, 3 + 1 / -1);
//table.Rows.Remove(table.Rows[0]);
Dictionary<(object, object), object> row;
foreach (DataRow dr in table.Rows)
{
row = new Dictionary<(object, object), object>();
foreach (DataColumn col in table.Columns)
{
object FirstcolName = table.Rows[0][col.ColumnName].ToString(); //index the first row with the column name
object SecondcolName = table.Rows[1][col.ColumnName].ToString(); //index the 2nd row with the column name
//string 3rdcolname = table.Rows[3][col.ColumnName].ToString(); //index the 2nd row with the column name
// Tuple<string,string> column_name_keys = new Tuple<string,string>(FirstcolName.ToString(), SecondcolName.ToString());
//col.ColumnName = column_name_keys;
// table.Rows[0].Delete();
row.Add((FirstcolName, SecondcolName), dr[col]); //add the column names as keys and data as values in the dicttionary.using a tuple of two column headers as key
}
int index = table.Rows.IndexOf(dr); //indexing eachrow to cnvert the value in each row to string
rows.Add(index.ToString(), row); //converting to string
}
string json = JsonConvert.SerializeObject(rows, Formatting.Indented);
File.WriteAllText(#"D:\Data\test.json", json);
}
}
}
Posting the developed code for people who might need it or might be stuck in a similar problem.
This code below works for the most part as it makes the dictionary structure. However it needs to be improved with introduction of Flexible nested dictionaries that can take any types of values(including Dictionaries). This one generates the Survey_level Dictionary atleast: The nested borehole dictionary structure can only be added when we have a class that combines Boreholes Dictionary, SurveyParameter Dictionary & SurveySetting Dictionary
...
public void ExcelReader(string path)
{
var stream = File.Open(path, FileMode.Open, FileAccess.Read);
var reader = ExcelReaderFactory.CreateReader(stream);
var result = reader.AsDataSet();
var tables = result.Tables.Cast<DataTable>();
//If you declared nested dict as object you couldn't do any operations with it that are provided by Dictionary, only the ones valid for all objects.
Dictionary<string, Dictionary<string, Dictionary<(string, string), object>>> dict_coll = new Dictionary<string, Dictionary<string, Dictionary<(string, string), object>>>();
Dictionary<string, Dictionary<(string, string), object>> rows = new Dictionary<string, Dictionary<(string, string), object>>();
Dictionary<(string, string), object> row_usable = new Dictionary<(string, string), object>();
foreach (DataTable table in tables)
{
Dictionary<(string, string), object> row;
foreach (DataRow dr in table.Rows)
{
row = new Dictionary<(string, string), object>();
foreach (DataColumn col in table.Columns)
{
string FirstcolName = table.Rows[0][col.ColumnName].ToString(); //index the first row with the column name
string SecondcolName = table.Rows[1][col.ColumnName].ToString(); //index the 2nd row with the column name
row.Add((FirstcolName, SecondcolName), dr[col]); //add the column names as keys and data as values in the dicttionary.using a tuple of two column headers as key
}
int index = table.Rows.IndexOf(dr); //indexing eachrow to cnvert the value in each row to string
rows.Add(index.ToString(), row); //converting to string
rows.Remove("0");
rows.Remove("1");
rows.Remove("3");
List<(string, string)> row_Keys = new List<(string, string)>(row.Keys);
List<object> row_vals = new List<object>(row.Values);
row_usable = row_Keys.Zip(row_vals, (k, v) => new { k, v }).ToDictionary(x => x.k, x => x.v);
}
dict_coll.Add(table.TableName.ToString(), rows);
}
var guid_data = rows.ElementAt(0).Value; //or use trygetvalue()
var SURVEY_ID = ("SurveyParameter", "SurveyId");
var BOREHOLE_ID = ("BoreholeParameter", "BoreholeId");
var LAYER_ID = ("Parameter", "LayerId");
Dictionary<string, object> guid_dict = new Dictionary<string, object>();
Dictionary<string, Dictionary<string,Dictionary<string,object>>> data_dict =
new Dictionary<string, Dictionary<string, Dictionary<string, object>>>();
//Dictionary<string,object?> data_dict =
// new Dictionary<string,object?>();
//Hashtable data_dict = new Hashtable;
Hashtable restructured = new Hashtable();
restructured.Add("ParameterGuid", guid_dict);
restructured.Add("Data", data_dict);
List<string> guid_dict_keys = guid_dict.Keys.OfType<string>().ToList();
List<string> data_dict_keys = data_dict.Keys.OfType<string>().ToList();
foreach (Dictionary<string, Dictionary<(string, string), object>> datasets in dict_coll.Values) // datasets= Dictionary<string, Dictionary<(string, string), object>>>no need for specified types with hashtable but have to cast the value KeyValuePair<string, Dictionary<string, Dictionary<(string, string), object>>>
{
foreach (KeyValuePair<(string, string), object> i in guid_data)
{
if (i.Key.Item1.EndsWith("Parameter") & !guid_dict_keys.Contains(i.Key.Item2))//string.IsNullOrEmpty()//convert guidict to single string //guid_dict.Keys i.Key.Item2))
{
guid_dict[i.Key.Item2] = i.Value; //convert guid
}
}
foreach (Dictionary<(string, string), object> dataset in datasets.Values) //NULlMaybe/get dict(tuple,value) /KeyValuePair<(string, string), object>datasets.Value as Hashtable, KeyValuePair<(string, string), object>
{
// get survey/borehole/layer Ids
string target_layer_id = dataset[LAYER_ID].ToString();
string target_survey_id = dataset[SURVEY_ID].ToString(); //
string target_borehole_id = dataset[BOREHOLE_ID].ToString();//
//NULL
var finished = false;
while (!finished)
{
if (data_dict.ContainsKey(target_survey_id))
{
var survey_set = data_dict[target_survey_id];
var boreholes = survey_set["Boreholes"] as boreholes_dict;
if (boreholes.ContainsKey(target_borehole_id))
{
var borehole_set = boreholes[target_borehole_id] as borehole_id_dict;
layers_dict layers = new layers_dict();
layers = borehole_set["Layers"] as layers_dict;
if (layers.ContainsKey(target_layer_id))
{
{ }
finished = true;
}
else
{
finished = true;
}
}
else
{
boreholes.Add(target_borehole_id, new Dictionary<string, object>());
boreholes[target_borehole_id].Add("BoreholeParameter", new Dictionary<string, object>());
boreholes[target_borehole_id].Add("BoreholeSetting", new Dictionary<string, object>());
boreholes[target_borehole_id].Add("Layers", new Dictionary<string, object>());
//boreholes = new Dictionary<string,Dictionary<string,Dictionary<string,object>>
}
}
else
{
//Dictionary<string, object> survey_nested_dict = new Dictionary<string, object>();
data_dict.Add(target_survey_id, new Dictionary<string, Dictionary<string,object>>());
data_dict[target_survey_id].Add("SurveyParameter", new Dictionary<string, object>());
data_dict[target_survey_id].Add("SurveySetting",new Dictionary<string, object>());
data_dict[target_survey_id].Add("Boreholes", new Dictionary<string, object>());
foreach (KeyValuePair<(string, string), object> cat_nam_val in dataset) // this is a hashtable version of dataset which is inside datasets.Values
{
var val_dict = new Dictionary<string, object>();
try
{
val_dict = data_dict[target_survey_id][cat_nam_val.Key.Item1];
}
catch
{
}
if (IsDictionary(val_dict)) ;
{
val_dict.Add(cat_nam_val.Key.Item2, cat_nam_val.Value);
}
}
}
}
}
}
string json_guid = JsonConvert.SerializeObject(guid_dict, Formatting.Indented);
File.WriteAllText(#"D:\Data\testjsons\test_guid_dict.json", json_guid);
string json = JsonConvert.SerializeObject(dict_coll, Formatting.Indented);
File.WriteAllText(#"D:\Data\testjsons\test2.json", json);
string json_data = JsonConvert.SerializeObject(data_dict, Formatting.Indented);
File.WriteAllText(#"D:\Data\testjsons\test_data_dict.json", json_guid);
}
}
}
EDIT:
The following code has achieved the structure shown above in the question description. I hope it helps anyone who is stuck in this problem.
public void ExcelReader(string path)
{
var stream = File.Open(path, FileMode.Open, FileAccess.Read);
var reader = ExcelReaderFactory.CreateReader(stream);
var result = reader.AsDataSet();
var tables = result.Tables.Cast<DataTable>();
//If you declared nested dict as object you couldn't do any operations with it that are provided by Dictionary, only the ones valid for all objects.
Dictionary<string, Dictionary<string, Dictionary<(string, string), object>>> dict_coll = new Dictionary<string, Dictionary<string, Dictionary<(string, string), object>>>();
Dictionary<string, Dictionary<(string, string), object>> rows = new Dictionary<string, Dictionary<(string, string), object>>();
Dictionary<(string, string), object> row_usable = new Dictionary<(string, string), object>();
foreach (DataTable table in tables)
{
Dictionary<(string, string), object> row;
foreach (DataRow dr in table.Rows)
{
row = new Dictionary<(string, string), object>();
foreach (DataColumn col in table.Columns)
{
string FirstcolName = table.Rows[0][col.ColumnName].ToString(); //index the first row with the column name
string SecondcolName = table.Rows[1][col.ColumnName].ToString(); //index the 2nd row with the column name
row.Add((FirstcolName, SecondcolName), dr[col]); //add the column names as keys and data as values in the dicttionary.using a tuple of two column headers as key
}
int index = table.Rows.IndexOf(dr); //indexing eachrow to cnvert the value in each row to string
rows.Add(index.ToString(), row); //converting to string
rows.Remove("0");
rows.Remove("1");
rows.Remove("3");
List<(string, string)> row_Keys = new List<(string, string)>(row.Keys);
List<object> row_vals = new List<object>(row.Values);
row_usable = row_Keys.Zip(row_vals, (k, v) => new { k, v }).ToDictionary(x => x.k, x => x.v);
}
dict_coll.Add(table.TableName.ToString(), rows);
}
var guid_data = rows.ElementAt(0).Value; //or use trygetvalue()
var SURVEY_ID = ("SurveyParameter", "SurveyId");
var BOREHOLE_ID = ("BoreholeParameter", "BoreholeId");
var LAYER_ID = ("Parameter", "LayerId");
Dictionary<string, object> guid_dict = new Dictionary<string, object>();
Dictionary<string,Dictionary<string, Dictionary<object, object>>> data_dict =
new Dictionary<string, Dictionary<string, Dictionary<object, object>>> ();
//Dictionary<string,object?> data_dict =
// new Dictionary<string,object?>();
//Hashtable data_dict = new Hashtable;
Hashtable restructured = new Hashtable();
restructured.Add("ParameterGuid", guid_dict);
restructured.Add("Data", data_dict);
List<string> guid_dict_keys = guid_dict.Keys.OfType<string>().ToList();
List<string> data_dict_keys = data_dict.Keys.OfType<string>().ToList();
foreach (Dictionary<string, Dictionary<(string, string), object>> datasets in dict_coll.Values) // datasets= Dictionary<string, Dictionary<(string, string), object>>>no need for specified types with hashtable but have to cast the value KeyValuePair<string, Dictionary<string, Dictionary<(string, string), object>>>
{
foreach (KeyValuePair<(string, string), object> i in guid_data)
{
if (i.Key.Item1.EndsWith("Parameter") & !guid_dict_keys.Contains(i.Key.Item2))//string.IsNullOrEmpty()//convert guidict to single string //guid_dict.Keys i.Key.Item2))
{
guid_dict[i.Key.Item2] = i.Value; //convert guid
}
}
foreach (Dictionary<(string, string), object> dataset in datasets.Values) //NULlMaybe/get dict(tuple,value) /KeyValuePair<(string, string), object>datasets.Value as Hashtable, KeyValuePair<(string, string), object>
{
// get survey/borehole/layer Ids
string target_layer_id = dataset[LAYER_ID].ToString();
string target_survey_id = dataset[SURVEY_ID].ToString(); //
string target_borehole_id = dataset[BOREHOLE_ID].ToString();//
//NULL
var finished = false;
while (!finished)
{
if (data_dict.ContainsKey(target_survey_id))
{
var survey_set = data_dict[target_survey_id];
var boreholes = survey_set["Boreholes"];
if (boreholes.ContainsKey(target_borehole_id))
{
var borehole_set = boreholes[target_borehole_id] as Dictionary<string, Dictionary<object, object>>;
//Hashtable layers = new Hashtable();
var layers = borehole_set["Layers"] as Dictionary<object, object>;
if (layers.ContainsKey(target_layer_id))
{
{ }
finished = true;
}
else
{
layers.Add(target_layer_id, new Dictionary<string, Dictionary<object, object>>
{
{"Parameter", new Dictionary<object, object>() },
{"LayerSetting", new Dictionary<object, object>()}
});
foreach (KeyValuePair<(string, string), object> cat_nam_val in dataset) // this is a hashtable version of dataset which is inside datasets.Values
{
var val_dict = new Dictionary<object, object>(); // Dictionary<string, object>();
try
{
var val_dicttt = layers[target_layer_id] as Dictionary<string, Dictionary<object, object>>; // extra variable for casting
val_dict = val_dicttt[cat_nam_val.Key.Item1];
}
catch
{
}
if (IsDictionary(val_dict)) ;
{
val_dict.Add(cat_nam_val.Key.Item2, cat_nam_val.Value);
}
}
finished = true;
}
}
else
{
boreholes.Add(target_borehole_id, new Dictionary<string, Dictionary<object, object>>
{
{ "BoreholeParameter", new Dictionary<object, object>() },
{ "BoreholeSetting", new Dictionary<object, object>()},
{ "Layers", new Dictionary<object, object>() }
});
foreach (KeyValuePair<(string, string), object> cat_nam_val in dataset) // this is a hashtable version of dataset which is inside datasets.Values
{
var val_dict = new Dictionary<object, object>();
try
{
var val_dictt = boreholes[target_borehole_id] as Dictionary<string, Dictionary<object, object>>;
val_dict = val_dictt[cat_nam_val.Key.Item1];
}
catch
{
}
if (IsDictionary(val_dict)) ;
{
val_dict.Add(cat_nam_val.Key.Item2, cat_nam_val.Value);
}
}
}
}
else
{
//1.use hashtable
//Dictionary<string, object> survey_nested_dict = new Dictionary<string, object>();
data_dict.Add(target_survey_id, new Dictionary<string, Dictionary<object, object>>());
data_dict[target_survey_id].Add("SurveyParameter", new Dictionary<object, object>()); //new Dictionary<object, object>()
data_dict[target_survey_id].Add("SurveySetting", new Dictionary<object, object>());
data_dict[target_survey_id].Add("Boreholes", new Dictionary<object, object>());
foreach (KeyValuePair<(string, string), object> cat_nam_val in dataset) // this is a hashtable version of dataset which is inside datasets.Values
{
var val_dict = new Dictionary<object, object>();// Dictionary<string, object>();
try
{
val_dict = data_dict[target_survey_id][cat_nam_val.Key.Item1];
}
catch
{
}
if (IsDictionary(val_dict)) ;
{
val_dict.Add(cat_nam_val.Key.Item2, cat_nam_val.Value);
}
}
}
}
}
}
string json_guid = JsonConvert.SerializeObject(guid_dict, Formatting.Indented);
File.WriteAllText(#"D:\Data\test_guid_dict.json", json_guid);
string json = JsonConvert.SerializeObject(dict_coll, Formatting.Indented);
File.WriteAllText(#"D:\Data\test2.json", json);
string json_data = JsonConvert.SerializeObject(data_dict, Formatting.Indented);
File.WriteAllText(#"D:\Data\test_data_dict.json", json_data);
string json_final_data = JsonConvert.SerializeObject(restructured, Formatting.Indented);
File.WriteAllText(#"D:\Data\test_restructured_data_dict.json", json_final_data);
}
}
}
Related
List<KeyValuePair> overrides added values
I am currently facing an issue where I want to add different values to the same Key in a foreach loop. List<KeyValuePair<string, Dictionary<string, string>>> sysList = new List<KeyValuePair<string, Dictionary<string, string>>>(); Dictionary<string, string> newSystem = new Dictionary<string, string>(); string line1=""; string line2=""; string quit=""; foreach(Worksheet ws in workbook.Worksheets) { while(quit != q) { newSystem.Clear(); line1 = Console.ReadLine(); line2 = Console.ReadLine(); quit = Console.ReadLine(); } newSystem.Add(line1, line2); sysList.Add(new KeyValuePair<string, Dictionary<string, string>>(ws.Name,newSystem)); } For the first iteration (within while) of the first Worksheet ws everything is fine. If the I choose to do >1 iterations within this Worksheet, there is a new entry added, but the Dictionary values are all the same, f.e.: syList[0]: "worksheetName","test1","test2" syList[1]: "worksheetName","test1","test2" syList[2]: "worksheetName","test1","test2" If there are several foreach iterations, the names stay the same, but the Dictionary Key and Values added by newSys are the same [AFTER the second foreach iteration]: syList[0]: "worksheetName1","test1","test2" syList[1]: "worksheetName1","test1","test2" syList[2]: "worksheetName1","test1","test2" syList[3]: "worksheetName2","test1","test2" syList[4]: "worksheetName2","test1","test2" Initially I tried using Dictionaries, but could not handle the same keys properly and did not find a proper solution except for using List. I am very grateful for any help provided. If there are additional details that you require, please, let me know. Edit: desired result (example): #########: ws.Name, line1, line2 syList[0]: "worksheetName1","ABC","1" syList[1]: "worksheetName1","DEF","2" syList[2]: "worksheetName1","ABC","5" syList[3]: "worksheetName2","ABD","4" syList[4]: "worksheetName2","ZZZ","1"
In case you don't want to maintain any uniqueness in the keys and just want a flat list, you can use the C#7 tuple syntax to build your list. List<string> sheetNames = new List<string>() { "worksheetName1", "worksheetName2" }; var sysList = new List<(string SheetName, string line1, string line2)>(); string line1 = string.Empty; string line2 = string.Empty; string quit = string.Empty; foreach (var sheet in sheetNames) { while (quit != "E") { line1 = Console.ReadLine(); line2 = Console.ReadLine(); quit = Console.ReadLine(); sysList.Add((sheet, line1, line2)); } quit = string.Empty; }
Try code below : List<List<string>> syList = new List<List<string>>() { new List<string>() {"worksheetName1","test1","test2"}, new List<string>() {"worksheetName1","test1","test2"}, new List<string>() {"worksheetName1","test1","test2"}, new List<string>() {"worksheetName2","test1","test2"}, new List<string>() {"worksheetName2","test1","test2"} }; Dictionary<string, Dictionary<string, List<string>>> dict = syList .GroupBy(x => x.First(), y => y) .ToDictionary(x => x.Key, y => y .GroupBy(a => a.Skip(1).FirstOrDefault(), b => b.Last()) .ToDictionary(a => a.Key, b => b.ToList())); //using normal looping Dictionary<string, Dictionary<string, List<string>>> dict2 = new Dictionary<string, Dictionary<string, List<string>>>(); foreach (List<string> sy in syList) { if (dict2.ContainsKey(sy[0])) { Dictionary<string, List<string>> tempDict = dict2[sy[0]]; if (tempDict.ContainsKey(sy[1])) { tempDict[sy[1]].Add(sy[2]); } else { List<string> newList = new List<string>() { sy[2] }; tempDict.Add(sy[1], newList); } } else { Dictionary<string, List<string>> newDict = new Dictionary<string, List<string>>(); newDict.Add(sy[1], new List<string> { sy[2] }); dict2.Add(sy[0], newDict); } }
How to get value of a specific value of a list in C#
var ctsDB = mooe.Files66.ToList(); Dictionary<string, string> mappedfields = new Dictionary<string, string>(); Dictionary<string, string> ctsfieldsValue = new Dictionary<string, string>(); for (int i = 0; i < ctsDB.Count; i++) { foreach(var item in mappedfields) { // this line returns the item.key string not the value of it. // item.key is the column name var rowValue = mooe.Files66.Select(k = >item.Key).ToList(); // ctsfieldsValue.Add(item.Value, rowValue); ctsfieldsValue.ToList(); } } I want to iterate through ctsDB List and get the row value of a specific column like this: if ctsDB [i] = fileID Field612 Fiel613 and I have these column names in the value field of ctsfieldsValue. I want to iterate on ctsDB[i] to get the value of column Field612 only. Can anyone provide a thought?
var ctsDB = mooe.Files66.ToList(); var mappedfields = new Dictionary<string, string>(); // I assume this is not empty in your real code. var ctsfieldsValue = new List<Dictionary<string, string>>(); foreach (var row in ctsDB) { var d = new Dictionary<string, string>(); foreach (var mapping in mappedfields) { var v = row[mapping.Key]; //throws if not found d[mapping.Value] = v; } ctsfieldsValue.Add(d); }
Get Json Object From QueryString c#
The best I found was that available solutions at stack do not have answer for nested json object, they only address liner json values. But I have data to send is like { ob: { a: "78", b: { a: "gffg", h: {m:67, j:"fff"} } } } If I want to do it in php i would just do $json = $_POST['ob']; $obj = json_decode($json); But In c# I can'not do that. So I would appreciate any built-in method if available and I would love to be helped to fix my following code I want to make a nested dictionary (I would prefer JOBject though). For ease of showing output I have serialized the result, What result I have achieved yet from following code is {"a":"78","ob":{},"ob.b":{"a":"gffg"},"ob.b.h":{"m":"67","j":"fff"}} but desired result is like sent data { "ob": { "a": "78", "b": { "a": "gffg", "h": {m:67, "j":"fff"} } } } Code is string getJsonStringFromQueryString() { Dictionary<string, object> dic = new Dictionary<string, object>(); var nvc = Request.QueryString; foreach (string key in nvc.Keys) { string[] values = nvc.GetValues(key); string tempKey = key; tempKey = tempKey.Replace("[", ".").Replace("]", ""); if (values.Length == 1) dic.Add(tempKey, values[0]); else dic.Add(tempKey, values); } //It is giving me {[ob.a, 78]} {[ob.b.a, gffg]} {[ob.b.h.m, 67]} {[ob.b.h.j, fff]} var result = makeNestedObject(dic); var json = new JavaScriptSerializer().Serialize(result); return json; } I am trying to add the leaf keys and their values as it is and all other keys as dictionary Dictionary<string, object> makeNestedObject(Dictionary<string, object> qsDictionar) { Dictionary<string, object> result = new Dictionary<string, object>(); foreach (string key in qsDictionar.Keys) { string temp = ""; if (key.Contains(".")) { string[] ar = key.Split('.'); if (ar.Length > 2) { for (int i = 0; i < ar.Length - 1; i++) { temp = ar[0]; for (int j = 1; j <= i; j++) { temp += "." + ar[j]; } //above is getting the previous key i want to use as dictionary, leaving the leaf key. try { Dictionary<string, object> forTry = (Dictionary<string, object>)result[temp]; } catch { result.Add(temp, new Dictionary<string, object>()); } } ((Dictionary<string, object>)result[temp]).Add(ar[ar.Length - 1], qsDictionar[key]); } else result.Add(ar[1], qsDictionar[key]); } } return result; }
Following method gives you complete solution for any json object. string getJsonStringFromQueryString() { Dictionary<string, object> dic = new Dictionary<string, object>(); var nvc = Request.QueryString; foreach (string key in nvc.Keys) { string[] values = nvc.GetValues(key); string tempKey = key; tempKey = tempKey.Replace("[", ".").Replace("]", ""); if (values.Length == 1) dic.Add(tempKey, values[0]); else dic.Add(tempKey, values); } string vald = Request.QueryString["ob"]; var result = makeNestedObject(dic); var json = new JavaScriptSerializer().Serialize(result); return json; } Dictionary<string, object> makeNestedObject(Dictionary<string, object> qsDictionar) { Dictionary<string, object> result = new Dictionary<string, object>(); foreach (string key in qsDictionar.Keys) { if (key.Contains(".")) { List<string> keysList = key.Split('.').ToList(); Dictionary<string, object> lastAddedDictionary = result; while (keysList.Count > 1) { if (!lastAddedDictionary.ContainsKey(keysList[0])) { Dictionary<string, object> temp = new Dictionary<string, object>(); lastAddedDictionary[keysList[0]] = temp; lastAddedDictionary = temp; } else lastAddedDictionary = (Dictionary<string, object>)lastAddedDictionary[keysList[0]]; keysList.RemoveAt(0); } lastAddedDictionary[keysList[0]] = qsDictionar[key]; } else { result.Add(key, qsDictionar[key]); } } return result; }
Compare Dictionary Key of type string to another string in C#
I'm actually trying to check if a string is equal to any of the key's in my Dictionary object. Here is what I have done so far: using (var oStreamReader = new StreamReader(path)) { Dictionary<String, String> typeNames = new Dictionary<string, string>(); typeNames.Add("Kind","nvarchar(1000)"); typeNames.Add("Name","nvarchar(1000)"); DataTable oDataTable = new DataTable(); var headLine = oStreamReader.ReadLine().Trim().Replace("\"", ""); var columnNames = headLine.Split(new[] { ';' }); String[] oStreamDataValues; /* *create DataTable header with specific datatypes and names */ int countCol = 0; foreach (string readColumn in columnNames) { if ((readColumn.ToString().Replace("\"", "").CompareTo(typeNames) == true)) { // this comparison doesn't work } } }
I am not quite sure what exactly you are trying to achieve. If you have a C# dictonary you can use linq to check for values that match the required value, e.g. string valueToCompare = "Value to match"; Dictionary<string, string> dict = new Dictionary<string, string> { {"Key 1", "A value"}, {"Key 2", "Another value"} }; bool found= dict.Values .Any(value => value.Equals(valueToCompare, StringComparison.CurrentCultureIgnoreCase) );
Since you want check if exist an entry in your Dictionary that as the same key of one of the values in your columnNames object I suggest you to use ContainsKey method
Dictionary<string, string> d = new Dictionary<string, string>(); string keyvalue; if (d.ContainsKey("value to find")) { if (d.TryGetValue("value to find", out keyvalue)) { //// here keyvalue variable has the value } else { ///value is null or throws exception } } else { ////key no exists }
I have solved this (by inspiration of Paul Houlston and Thomas Lielacher) string headLine = oStreamReader.ReadLine().Trim().Replace("\"", ""); string columnNames = headLine.Split(new[] { ';' }); foreach (string readColumn in columnNames) { if (typeNames.Keys.Contains(readColumn, StringComparer.CurrentCultureIgnoreCase) == true) { DataColumn oDataColumn = new DataColumn(readColumn,typeof(System.String)); oDataTable.Columns.Add(oDataColumn); } }
Compare two dictionaries and merge in to other dictionary with keys and values present in both dictionaries
I am working on small utility and as it turns out I have to compare two dictionaries and export the data in Excel in the below format Key dict1value dict2value If a key is available in both the dictionaries. My output would be Key dict1value dict2value If a key is available in firstdictionary and not in second . My output would be Key dict1Value "NotAvailable" If a key is available in second dictionary but not in first . My output would be key "Not Available" dict2value. To be more clear, The key column in Excel consists of keys from both the dictionaries.The value columns will have values depending on the availability. Though the below code is working,I would like to know if I can optimize the performance even more. Note : Please ignore the bad naming conventions public void validateTwoDictionaries() { Dictionary<string, string> dict1 = new Dictionary<string, string>(); Dictionary<string, string> dict2 = new Dictionary<string, string>(); Dictionary<string, KeyValuePair<string, string>> complexdicts = new Dictionary<string, KeyValuePair<string, string>>(); dict1.Add("A", "1"); dict1.Add("B", "2"); dict2.Add("A", "2"); dict2.Add("C", "3"); dict2.Add("D", "4"); int count1 = dict1.Keys.Count; int count2 = dict2.Keys.Count; int maxcount = count2; if (count1 > count2) { maxcount = count1; } for (int i = 0; i < maxcount; i++) { string dict1Key = string.Empty; string dict2Key = string.Empty; //need to iterate both the dictionaries at one go. if (i < count1) { dict1Key = dict1.Keys.ElementAt(i); } if (i < count2) { dict2Key = dict2.Keys.ElementAt(i); } // do the work for first dictionary, try to decouple to reuse for the 2nd dict if (dict1Key != string.Empty) { if (!complexdicts.Keys.Contains(dict1Key)) { if (dict2.Keys.Contains(dict1Key)) { // Add to the complext dictionary complexdicts.Add(dict1Key, new KeyValuePair<string, string>(dict1[dict1Key], dict2[dict1Key])); } else { complexdicts.Add(dict1Key, new KeyValuePair<string, string>(dict1[dict1Key], "Not Available")); } } } // do the work for second dictionary if (dict2Key != string.Empty) { if (!complexdicts.Keys.Contains(dict2Key)) { if (dict1.Keys.Contains(dict2Key)) { // Add to the complext dictionary complexdicts.Add(dict2Key, new KeyValuePair<string, string>(dict1[dict2Key], dict2[dict2Key])); } else { complexdicts.Add(dict2Key, new KeyValuePair<string, string>("Not Available", dict2[dict2Key])); } } } } dict1 and dict2 are sample dictionaries and complexdicts object is what I want to export to excel. Please let me know if I can do this in better way.
How about this? Dictionary<string, string> dict1 = new Dictionary<string, string>(); Dictionary<string, string> dict2 = new Dictionary<string, string>(); Dictionary<string, KeyValuePair<string, string>> complexdicts = new Dictionary<string, KeyValuePair<string, string>>(); dict1.Add("A", "1"); dict1.Add("B", "2"); dict2.Add("A", "2"); dict2.Add("C", "3"); dict2.Add("D", "4"); var allKeys = dict1.Keys.Union(dict2.Keys); foreach (var key in allKeys) { string val1; if (!dict1.TryGetValue(key, out val1)) { val1 = "Not Available"; } string val2; if (!dict2.TryGetValue(key, out val2)) { val2 = "Not Available"; } complexdicts.Add(key, new KeyValuePair<string, string>(val1, val2)); }
How about this? Dictionary<string, string> dict1 = new Dictionary<string, string>(); Dictionary<string, string> dict2 = new Dictionary<string, string>(); dict1.Add("A", "1"); dict1.Add("B", "2"); dict2.Add("A", "2"); dict2.Add("C", "3"); dict2.Add("D", "4"); var allKeys = dict1.Keys.Union(dict2.Keys); // case 1 List<Tuple<string, string, string>> unionValues = new List<Tuple<string, string, string>>(); foreach (var key in allKeys) { unionValues.Add(new Tuple<string, string, string>(key, dict1.ContainsKey(key) ? dict1[key] : "N/A" , dict2.ContainsKey(key) ? dict2[key] : "N/A")); } // case 2 var result = (from key in allKeys select new Tuple<string, string, string>(key, dict1.ContainsKey(key) ? dict1[key] : "N/A", dict2.ContainsKey(key) ? dict2[key] : "N/A")).ToList();