I am trying to access a dictionary nested inside another dictionary.
The code I wrote is:
foreach (var entry in source)
{
int i = 0;
str = str + i + ": key: " + entry.Key + "; value = " + entry.Value +"; ";
// do something with entry.Value or entry.Key
}
and for some elements the value is System.Collections.Generic.Dictionary`2[System.String,System.Object]
I would like to access this dictionary when the inner value has a given value, as "Department".
Any idea on how to do it?
I would like to access this dictionary when the inner key has a given
value, as "Department"
Assuming you have a dictionary like this:
var source = new Dictionary<string, Dictionary<String, Object>>();
foreach (var outerEntry in source)
{
foreach (var innerEntry in outerEntry.Value)
{
if(innerEntry.Key == "Department")
{
// do something
Console.WriteLine("Key:{0} Value:{1}", innerEntry.Key, innerEntry.Value);
}
}
}
If the Value is a dictionary you could loop through the underlying dictionary keys:
foreach (var entry in source)
{
int i = 0;
str = str + i + ": key: " + entry.Key + "; value = "
if (entry.Value is IDictionary)
}
str = str + " { ";
foreach (var innerentry in (entry.Key as IDictionary))
{
str = str + innerentry.Key + "; value = " + innerentry.Value +"; ";
}
str = str + " } ";
}
else
str = str + entry.Value +"; ";
// do something with entry.Value or entry.Key
}
Related
public partial class Form1 : Form
{
public static Dictionary<string,string> contactList = new Dictionary<string,string>();
public Form1()
{
InitializeComponent();
Text = "My Telephone Directory";
}
private void txtAdd_Click(object sender, EventArgs e)
{
String name = txtName.Text;
String teleNo = txtTelephone.Text;
contactList.Add(name,teleNo);
txtContactList.Text = "Added " + name;
}
private void txtClear_Click(object sender, EventArgs e)
{
txtContactList.Text = " ";
}
private void txtList_Click(object sender, EventArgs e)
{
String contactLists="";
foreach (KeyValuePair<string,string> kvp in contactList)
{
contactLists += "Name: " + contactList.Keys.ToString()+ " Phone No: " + contactList.Values + Environment.NewLine;
}
txtContactList.Text = contactLists;
}
private void txtSearch_Click(object sender, EventArgs e)
{
String contactLists = "";
foreach (KeyValuePair<string, string> kvp in contactList)
{
contactLists += "Name: " + contactList.Keys.ToString() + " Phone No: " + contactList.Values + Environment.NewLine;
if (contactList.Keys.ToString() == txtName.Text)
{
contactLists += "Name: " + contactList.Keys.ToString() + " Phone No: " + contactList.Values.ToString() + Environment.NewLine;
}
txtContactList.Text = contactLists;
}
}
private void button1_Click(object sender, EventArgs e)
{
OpenFileDialog openFileDialog1 = new OpenFileDialog();
}
}
I cant enumerate the dictionary, see the txtList_Click eventhandler.
If I do what im doing, I get System.Collections.Generic.Dictionary2+KeyCollection[System.String,System.String] Phone No: System.Collections.Generic.Dictionary2+ValueCollection[System.String,System.String].
If I do contactList.Key like im supposed to I get System.Collections.Generic.Dictionary
You are calling the ToString() methods on the collection objects rather then the specific key and value pair. Try this:
foreach (KeyValuePair<string,string> kvp in contactList)
{
contactLists += "Name: " + kvp.Key + " Phone No: " + kvp.Value + Environment.NewLine;
}
Iterating the Dictionary and building the contactLists string
To iterate the Dictionary and build up a string, just use the KeyValuePair variable (kvp) that you've assigned in the foreach:
foreach (KeyValuePair<string, string> kvp in contactList)
{
contactLists += "Name: " + kvp.Key
+ " Phone No: " + kvp.Value + Environment.NewLine;
...
However, concatenating the string contactLists in a loop is inefficient. StringBuilder would help here, or, instead of the loop, you can simply project out each key value pair "string" with a Linq Select, and then Join them.
var contactLists =
string.Join(Environment.NewLine,
contactList.Select(cl => string.Format("Name: {0} Phone No: {1}",
cl.Key, cl.Value)));
Re searching the dictionary
One of the benefits of using a Dictionary (or HashSet) is that it offers indexed / keyed lookups, so you don't need to iterate the full collection to find an element by manual comparison of keys. So if you've keyed phone numbers by the person's name, this would be a more typical usage:
var searchPhone = contactList[txtName.Text];
To make this more robust, you'd want to check if the key exists first, e.g. with ContainsKey or TryGetValue:
string searchPhone;
if (contactList.TryGetValue(text.Name, out searchPhone))
... found, use searchPhone
else
... not found
I am currently working on a program that takes JSON input and deserializes it using JSON.NET into a dynamic ExpandoObject. Then through a function, I want to dump it out into another textbox to show what it could possibly represent as C# objects. How would I indent my string to show my hierarchical ExpandoObject and take it from a flat list of data to a tree structure of data I can send to a textbox as a string?
Here is some of the code I am using:
if (tbxJSON.Text != "")
{
// Create an ExpandoObjectConverter in order to hold the dynamic parsed JSON.
var converter = new ExpandoObjectConverter();
dynamic convertedJSON = JsonConvert.DeserializeObject<ExpandoObject>(tbxJSON.Text, converter);
tbxCSharp.Text = "";
// Loop through the ExpandoObject and print out all of the values in the dynamic object using a recursive function.
foreach (var property in (IDictionary<string, object>)convertedJSON)
sb.Append(ExpandoToString(property.Value, property.Key));
// Set C# output to contents of StringBuilder.
tbxCSharp.Text = sb.ToString();
}
private string ExpandoToString(object propVal, string propName)
{
string retStr = "";
// If we are dealing with nested JSON
if (propVal.GetType() == typeof(ExpandoObject))
{
// Append this object type.
sb.Append(Indent(indentIdx) + UppercaseFirst(propName) + " " + propName + " consists of..." + Environment.NewLine);
foreach (var prop in (IDictionary<string, object>)propVal)
{
if (prop.Value.GetType() == typeof(ExpandoObject))
sb.Append(ExpandoToString(prop.Value, prop.Key));
else
{
if (prop.Value.GetType() == typeof(List<dynamic>))
{
// TO DO
}
else
sb.Append(ExpandoToString(prop.Value, prop.Key));
}
}
}
else
retStr = propVal.GetType() + " : " + propName + " = " + propVal + Environment.NewLine;
return retStr;
}
Test JSON:
{"airline":"Oceanic","number":815,"departure":{"IATA":"SYD","time":"2004-09-22 14:55","city":"Sydney"},"arrival":{"IATA":"LAX","time":"2004-09-23 10:42","city":"Los Angeles"}}
You should supply your current indent as a parameter to the ExpandoToString() method and increment it any time it calls itself.
private string ExpandoToString(object propVal, string propName, int indent = 0)
{
...
// Append this object type.
sb.Append(Indent(indent) + UppercaseFirst(propName) + " " + propName + " consists of..." + Environment.NewLine);
...
sb.Append(ExpandoToString(propVal, propName, indent + 1) ...);
I am looking for the best way to compare XML data with a string.
the data is stored in a xml called test.xml, and must be compared with the name descendant, if there is a match more info from the xml must be added to a textbox and picture box.
My ( working ) code:
var xmlDocument = XDocument.Load("test.xml"); // XML koppellen
var key1 = xmlDocument.Descendants("NAME"); // XML filepath
var key2 = xmlDocument.Descendants("TITLE"); // XML titel
var key3 = xmlDocument.Descendants("BRAND"); // XML afbeelding
var key4 = xmlDocument.Descendants("TYPE"); // XML merk
var key5 = xmlDocument.Descendants("SOORT"); // XML type
var key6 = xmlDocument.Descendants("NAAM"); // XML naam
List<string> file = new List<string>();
List<string> title = new List<string>();
List<string> brand = new List<string>();
List<string> type = new List<string>();
List<string> soort = new List<string>();
List<string> naam = new List<string>();
int i = 0;
foreach (var key in key1)
{
file.Add(key.Value.Trim());
}
foreach (var key in key2)
{
title.Add(key.Value.Trim());
}
foreach (var key in key3)
{
brand.Add(key.Value.Trim());
}
foreach (var key in key4)
{
type.Add(key.Value.Trim());
}
foreach (var key in key5)
{
soort.Add(key.Value.Trim());
}
foreach (var key in key6)
{
naam.Add(key.Value.Trim());
}
foreach (var Name in naam)
{
if (textBox3.Text.ToString() == Name.ToString())
{
PDFLocation = file[i].ToString();
pictureBox1.Image = pdfhandler.GetPDFthumbNail(PDFLocation);
textBox4.Text =
title[i].ToString() + "\r\n" +
brand[i].ToString() + "\r\n" +
type[i].ToString() + "\r\n" +
soort[i].ToString() + "\r\n" +
textBox3.Text + "\r\n";
}
i++;
}
]
I think this is not the best way to do it, but cant see a better way....
Update: solution:
foreach (XElement element in xmlDocument.Descendants("PDFDATA"))
{
if (textBox3.Text.ToString() == element.Element("NAAM").Value.Trim())
{
PDFLocation = element.Element("NAME").Value.ToString();
pictureBox1.Image = pdfhandler.GetPDFthumbNail(PDFLocation);
textBox4.Text =
element.Element("TITLE").Value + "\r\n" +
element.Element("BRAND").Value + "\r\n";
break;
}
}
Instead of thinking of the xml and a bunch of individual lists of data, it helps to think of it more as objects. Then you can loop through each element one at a time and don't need to split it up into individual lists. This not only removes duplicate code but more importantly creates a better abstraction of the data you are working with. This makes it easier to read and understand what the code is doing.
foreach (XElement element in xmlDocument.Elements())
{
if (textBox3.Text.ToString() == element.Element("NAAM").Value)
{
PDFLocation = element.Element("NAAM").Value;
pictureBox1.Image = pdfhandler.GetPDFthumbNail(PDFLocation);
textBox4.Text =
element.Element("Title").Value + "\r\n" +
element.Element("Brand").Value + "\r\n" +
element.Element("Type").Value + "\r\n"
// access rest of properties...
}
}
I have method in C#, I have to return all values from ArrayList.
public string vyhledavaniOS()
{
foreach (Vozidlo voz in nabídka)
{
if (voz is OsobníVůz)
return (voz.TypVozidla() + ": SPZ: " + voz.JakaSPZ + ", Značka: " + voz.JakaZnacka + ", Barva: " + voz.JakaBarva);
}
}
This code returns only one value, is there any way, how to return all values?
Yes, you need to change the method to return an array of strings instead of only one string value. Something like this:
public List<string> vyhledavaniOS()
{
List<string> listToReturn = new List<string>();
foreach (Vozidlo voz in nabídka)
{
if (voz is OsobníVuz)
listToReturn.Add((voz.TypVozidla() + ": SPZ: " + voz.JakaSPZ + ", Znacka: " + voz.JakaZnacka + ", Barva: " + voz.JakaBarva));
}
return listToReturn;
}
I need to grab all the FIELD and VALUES from a POST.
I have the follow which only return the FIELDs but no Values.
NameValueCollection authForm = Request.Form;
String[] a = authForm.AllKeys;
for (i = 0; i < a.Length; i++)
{
frm += ("Form: " + a[i] + " : " + "<br>");
}
Response.Write(frm);
What can I add this the frm string to show the VALUES ?
UPDATE:
I used the initial code of
NameValueCollection authForm = Request.Form;
foreach (string key in authForm.AllKeys)
{
frm += ("Key: " + key + ", Value: " + authForm[key] + "<br/>");
}
which worked great. I will try the new variation below.
NameValueCollection authForm = Request.Form;
StringBuilder sb = new StringBuilder();
foreach (string key in authForm.AllKeys)
{
sb.AppendFormat(
"Key: {0}, Value: {1}<br/>",
HttpUtility.HtmlEncode(key),
HttpUtility.HtmlEncode(authForm[key])
);
}
Response.Write(sb.ToString());