Related
In my code i declared like this :
public string[] s ;
and i need to use this string like this :
s["Matthew"]="Has a dog";
s["John"]="Has a car";
when i use s["Matthew"] an error appears and it says "Cannot implicitly convert 'string' to 'int'" .
How can I make a string array to have string index ?
if i write this in php it works :
array() a;
a["Mathew"]="Is a boy";
I need it to work also in asp.net !
public Dictionary<string, string> s;
MSDN documentation
In C#, you cannot access an array element using, as array index, a string.
For this reason you have that cast error, because the index of an array is, by definition of an array, an integer.
Why don't you use a data structure like a dictionary?
var dict = new Dictionary<string,string>();
dict.Add("John","I am John");
//print the value stored in dictionary using the string key
Console.WriteLine(dict["John"]);
Array works on indexes and indexes are in numbers but you are passing string that's why you are getting error, #Christian suggest you to use Dictionary
Dictionary<string, string> dict = new Dictionary<string, string>()
{
{"key1", "value1"},
{"key2", "value2"},
{"key3", "value3"}
};
// retrieve values:
foreach (KeyValuePair<string, string> kvp in dict)
{
string key = kvp.Key;
string val = kvp.Value;
// do something
}
I need a two column list like:
List<int,string> mylist= new List<int,string>();
it says
using the generic type System.collection.generic.List<T> requires 1 type arguments.
Depending on your needs, you have a few options here.
If you don't need to do key/value lookups and want to stick with a List<>, you can make use of Tuple<int, string>:
List<Tuple<int, string>> mylist = new List<Tuple<int, string>>();
// add an item
mylist.Add(new Tuple<int, string>(someInt, someString));
If you do want key/value lookups, you could move towards a Dictionary<int, string>:
Dictionary<int, string> mydict = new Dictionary<int, string>();
// add an item
mydict.Add(someInt, someString);
You could use an immutable struct
public struct Data
{
public Data(int intValue, string strValue)
{
IntegerData = intValue;
StringData = strValue;
}
public int IntegerData { get; private set; }
public string StringData { get; private set; }
}
var list = new List<Data>();
Or a KeyValuePair<int, string>
using Data = System.Collections.Generic.KeyValuePair<int, string>
...
var list = new List<Data>();
list.Add(new Data(12345, "56789"));
With the new ValueTuple from C# 7 (VS 2017 and above), there is a new solution:
List<(int,string)> mylist= new List<(int,string)>();
Which creates a list of ValueTuple type. If you're targeting .NET Framework 4.7+ or .NET/.NET Core, it's native, otherwise you have to get the ValueTuple package from nuget.
It's a struct opposing to Tuple, which is a class. It also has the advantage over the Tuple class that you could create a named tuple, like this:
var mylist = new List<(int myInt, string myString)>();
That way you can access like mylist[0].myInt and mylist[0].myString
Since your example uses a generic List, I assume you don't need an index or unique constraint on your data. A List may contain duplicate values. If you want to insure a unique key, consider using a Dictionary<TKey, TValue>().
var list = new List<Tuple<int,string>>();
list.Add(Tuple.Create(1, "Andy"));
list.Add(Tuple.Create(1, "John"));
list.Add(Tuple.Create(3, "Sally"));
foreach (var item in list)
{
Console.WriteLine(item.Item1.ToString());
Console.WriteLine(item.Item2);
}
Use C# Dictionary datastructure it good for you...
Dictionary<string, int> dict = new Dictionary<string, int>();
dict.Add("one", 1);
dict.Add("two", 2);
You can retrieve data from Ditionary in a simple way..
foreach (KeyValuePair<string, int> pair in dict)
{
MessageBox.Show(pair.Key.ToString ()+ " - " + pair.Value.ToString () );
}
For more example using C# Dictionary... C# Dictionary
Navi.
Not sure about your specific scenario, but you have three options:
1.) use Dictionary<..,..>
2.) create a wrapper class around your values and then you can use List
3.) use Tuple
List<Tuple<string, DateTime, string>> mylist = new List<Tuple<string, DateTime,string>>();
mylist.Add(new Tuple<string, DateTime, string>(Datei_Info.Dateiname, Datei_Info.Datum, Datei_Info.Größe));
for (int i = 0; i < mylist.Count; i++)
{
Console.WriteLine(mylist[i]);
}
For that, you could use a Dictionary where the int is the key.
new Dictionary<int, string>();
If you really want to use a list, it could be a List<Tuple<int,string>>() but, Tuple class is readonly, so you have to recreate the instance to modifie it.
I have a json object which is been converted to list of Dictionary. The json is as follows:
{
"DataList":
{"Non Fuel":
{
"sn":"/DataXmlProduct/Customers/DataXml/Customer/DueDate",
"ItemCode":"/DataXmlProduct/Customers/DataXml/Customer/InvoiceNo",
"Qty":"/DataXmlProduct/Customers/DataXml/Customer/CustomerNo",
"Amount":"DataXml/Customer/TotalCurrentCharges"
},
"Fuel":{
"sn":"/DataXmlProduct/Customers/DataXml/Customer/InvoiceNo",
"ItemCode":"/DataXmlProduct/Customers/DataXml/Customer/InvoiceNo",
"Amount":"DataXml/Customer/TotalCurrentCharges"
}
}
}
The result is (Dictionary<string, object>), Here the value of each dictionary is again a dictionary and I need to dynamically iterate through each values of the dictionary and get the last key & value where the value is a Xpath and need to get the values from the xpath.
Kindly help me with a solution to iterate through the dictionary. It should be generic since the json format can vary based on user input.
Assuming that the actual values (such as the contents of fuel) come out as a KeyValuePair<string, object>, then you could do this with a recursive method:
public static void ParseData(object source)
{
Dictionary<string, object> Dict;
KeyValuePair<string, object> Kvp;
if ((Dict = source as Dictionary<string,object>) != null)
{
foreach(var kvp in Dict)
{
Console.WriteLine(kvp.Key);
ParseData(kvp.Value);
}
}
elseif ((Kvp = source as KeyValuePair<string, object>) != null)
{
Console.WriteLine("{0}{1}", Kvp.Key, Kvp.Value);
}
}
This makes an assumption or two, but that will iterate through all the data assuming its made of dictionaries and kvps.
Edit: If you've got an XPath and want to get a node then what you'll need to do is prepare an XMLDocument with the data in. You can use the code above to walk through the data to help you build an XMLDocument and then query the document with your XPath.
Here's the basic code for processing all the data:
static void IterateDictionary(Dictionary<string, object> dictionary)
{
foreach (var pair in dictionary)
{
System.Console.WriteLine("Processing key: " + pair.Key);
object value = pair.Value;
var subDictionary = value as Dictionary<string, object>;
if (subDictionary != null)
{
// recursive call to process embedded dictionary
// warning: stackoverflowexception might occur for insanely embedded data: dictionary in dictionary in dictionary in . etc
IterateDictionary(subDictionary);
}
else
{
// process data
System.Console.WriteLine("data: {0}", value);
}
}
}
hope this helps
i'll suggest using Json.NET to serialize your objects, however, you've mentioned that the input is dynamic, but are the attributes standardized? Looking at your sample, there are several repeated fields. You can deserialize the json into your classes by doing
JsonConvert.DeserializeObject<YOUR_CUSTOM_OBJECT>
The .NET Dictionary<TKey, TValue> object allows assignment of key/values like so:
Dictionary<string, string> dict = new Dictionary<string, string>();
dict["1"] = "foo";
dict["2"] = "bar";
but I cannot use a Dictionary like so:
Dictionary<string, string> dict = new Dictionary<string, string>();
dict["F1"]["F2"]["F3"] = "foo";
dict["2"]["X"] = "bar";
Is there a collection in .NET which allows me to nest [], or would I have to create my own?
If I have to create my own, how would I do this?
EDIT:
It would also be useful if I could have implementations which expect unique keys, like so:
dict["F1"]["F2"]["F3"] = "foo";
dict["F1"]["F2"]["F3"] = "bar"; //result is "bar" because "foo" was overridden
and an implementation where a key can be used more than once
dict["F1"]["F2"]["F3"] = "foo";
dict["F1"]["F2"]["F3"] = "bar"; //result can be "foo" and "bar"
Is this possible?
EDIT (as per Jon Skeet's question):
I want to use the structure like so (as a very rough example):
json["data"]["request"]["name"] = "username";
json["data"]["request"]["pass"] = "password";
resolves to
{ data: { request: { name: "username", pass: "password" } } }
and equally there would be an equivalent for XML etc.
Having a requirement for arbitrarily long nesting, I have come up with the following solution, which as far as I can see, doesn't break, according to my test:
public class NestedDictionary<K, V> : Dictionary<K, NestedDictionary<K, V>>
{
public V Value { set; get; }
public new NestedDictionary<K, V> this[K key]
{
set { base[key] = value; }
get
{
if (!base.Keys.Contains<K>(key))
{
base[key] = new NestedDictionary<K, V>();
}
return base[key];
}
}
}
TEST:
NestedDictionary<string, string> dict = new NestedDictionary<string, string>();
dict["one"].Value = "Nest level 1";
dict["one"]["two"]["three"].Value = "Nest level 3";
dict["FieldA"]["FieldB"].Value = "Hello World";
Console.WriteLine(dict["one"].Value);
Console.WriteLine(dict["one"]["two"]["three"].Value);
Console.WriteLine(dict["FieldA"]["FieldB"].Value);
You can do this using the standard Dictionary, you just have to declare the nesting:
Dictionary<string, Dictionary<string, string>> dict = ...
string test = dict["first"]["second"]
Dictionary<string, Dictionary<string, Dictionary<string, string>>> dict = ...
string test = dict["first"]["second"]["third"]
etc
The original Dictionary COM object which was created to work with vb6 would respond to an attempt to access a non-existent item by creating a new item of type Dictionary with the corresponding name. This approach allows something to be stored to MyDict["Foo"]["Bar"] without having to first create MyDict["Foo"]. The problem with this approach is that while one would want to add "Foo" to MyDict when performing a write to MyDict["Foo"]["Bar"], one would rather not create such an item if one was attempting to e.g. evaluate MyDict["Foo"]["Bar"].ValueOrDefault(someDefaultValue).
I've used such collections, since they can be handy for modeling certain things (conceptually they're a lot like XML documents). One workable approach is to declare that dictionaries which contain nothing but other dictionaries are considered semantically as non-entities which may be removed at any opportunity. When implicitly adding a subcollection, set a flag in the item to which it's added it indicating that it should be checked for items that may be deleted (or keep a counter of how many such items may exist). Then with some reasonable frequency, scan through the dictionaries and remove such "dead" items.
An alternative approach is to have the indexer from the dictionary not return an actual item, but instead return an "ephemeral indexer" type, which keeps a reference to the parent object and has internal methods GetNestedForReading, SetNestedForReading, GetValue, and SetValue, which chain back to it. Then a statement Foo["Bar"]["Boz"] = "George"; will end up effectively performing Foo.SetNestedForReading("Bar").SetValue("Boz", "George"); while z = Foo["Bar"]["Boz"]; will effectively perform Foo.GetNestedForReading("Bar").GetValue("Boz");. Calling SetNestedForReading method with a non-existent key will create and return a new nested item; the GetNestedForReading method will an immutable "empty" item. Using this approach will thus avoid creating empty items.
Although the latter approach is more complicated than the former, it has another advantage. It's possible to have each node to individually hold its collection as either a shared deeply-immutable dictionary or an unshared mutable one; if a GetNestedForWriting call sees that the nested object is immutable, it can construct a new shallowly-mutable object holding the same items. If one defines the cloning method for a mutable node as creating a new immutable node with (immutable) clones of all subnodes, and the cloning method of an immutable node as returning itself, cloning trees that are mostly immutable becomes very cheap. If one had a newly-cloned (thus immutable) four-level tree with sixteen items on each level (65,536 leaf nodes total) and all the nodes were shared-immutable, updating a leaf node would only require replacing one leaf and four other nodes with mutable ones. Cloning the tree again would only require creating new immutable objects for the nodes which had been replaced with mutable ones (e.g. copying five things). Although one would have the convenience of a fully-mutable tree, one would have the efficiency advantages of an immutable one.
The biggest "problem" I see with this approach is that to avoid some weird behaviors one must require the use of syntax like MyDict["Foo"]["Bar"].Value = "George". If implicit conversion operators were used to avoid that requirement, someone would expect a statement like var st = MyThing["Foo"]["Bar"]; to define st as a string snapshot of whatever MyThing["Foo"]["Bar"] holds at that moment; instead it would define it as something that will index MyThing["Foo"]["Bar"]. If one had to use .Value to read or write strings from such a type, the fact that the variable wasn't a string would be apparent. If one used implicit operators to allow such assignments, the behavior would be odd. It's too bad there's no way a function can specify "do not allow this return value to be used for type inference".
Incidentally, it's possible to have the indexer type be a class or a generic struct. If it's a class, an access to foo["Bar"]["boz"]["baz"]... nested N deep would likely require the creation of N temporary heap objects. If it's a generic struct, it would entail the creation of N structs, but the more-deeply-nested structs would get bigger. For reasonable levels of nesting, generic structs would probably be slightly more efficient, but classes would probably be easier to work with.
You have to decide on either supporting a fixed number of string keys to look up, or provide a more general key mechanism if the number of keys can vary. For the first case try the following:
Dictionary<string,Dictionary<string,string>> dict =
Dictionary<string,Dictionary<string,string>>();
dict["F1"]["F2"] = "foo";
Dictionary<string,Dictionary<string,Dictionary<string,string>>> dict2 =
Dictionary<string,Dictionary<string,string>>();
dict2["F1"]["F2"]["F3"] = "bar";
For the second case, you could do the following:
Dictionary<string[],string> dict = new Dictionary<string[],string>(new MyEqualityComparer());
dict[new string[] {"F1","F2"}] = "foo";
dict[new string[] {"F1","F2","F3"}] = "bar";
where the class MyEqualityComparer would be something like:
public class MyEqualityComparer : IEqualityComparer<string[]>
{
public int GetHashCode(string[]item)
{
int hashcode = 0;
foreach (string s in item)
{
hashcode |= s.GetHashCode();
}
return hashcode;
}
public bool Equals(string [] a, string [] b)
{
if (a.Length != b.Length)
return false;
for (int i = 0; i < a.Length; ++i)
{
if (a[i] != b[i])
return false;
}
return true;
}
Use a Dictionary as TValue:
var dict2 = new Dictionary<string, Dictionary<string, string>>();
var dict3 = new Dictionary<string, Dictionary<string, Dictionary<string, string>>>();
for example:
var dict =
new Dictionary<string, Dictionary<string, string>>
{
{
"F1", new Dictionary<string, string>
{
{"F2", "foo"}
}
}
};
dict["F1"]["F2"] = "bar";
I think, your case is good place to use DynamicObject. I'll create an example for json using Dictionary<string, object> internally.
Same idea can be used for xml also.
string json = #"{""Name"":""Joe"",
""Age"":30,
""Address"":{ ""City"":""NY"" }}";
dynamic dynObj = new DynamicJson(json);
Console.WriteLine(dynObj.Name);
Console.WriteLine(dynObj.Age);
Console.WriteLine(dynObj.Address.City);
--
public class DynamicJson : DynamicObject
{
Dictionary<string, object> _Dict;
public DynamicJson(string json)
{
_Dict = (Dictionary<string, object>)new JavaScriptSerializer().DeserializeObject(json);
}
DynamicJson(Dictionary<string, object> dict)
{
_Dict = dict;
}
public override bool TryGetMember(GetMemberBinder binder, out object result)
{
result = null;
object obj;
if (!_Dict.TryGetValue(binder.Name, out obj)) return false;
if (obj is Dictionary<string, object>)
{
result = new DynamicJson((Dictionary<string, object>)obj);
}else
{
result = obj;
}
return true;
}
}
I'm looking for the simplest way of converting a query string from an HTTP GET request into a Dictionary, and back again.
I figure it's easier to carry out various manipulations on the query once it is in dictionary form, but I seem to have a lot of code just to do the conversion. Any recommended ways?
HttpUtility.ParseQueryString() parses query string into a NameValueCollection object, converting the latter to an IDictionary<string, string> is a matter of a simple foreach. This, however, might be unnecessary since NameValueCollection has an indexer, so it behaves pretty much like a dictionary.
Here is how I usually do it
Dictionary<string, string> parameters = HttpContext.Current.Request.QueryString.Keys.Cast<string>()
.ToDictionary(k => k, v => HttpContext.Current.Request.QueryString[v]);
How about HttpUtility.ParseQueryString?
Just add a reference to System.Web.dll
Same as Sean, but with Linq (and a function you can copy and paste):
public static Dictionary<string, string> ParseQueryString(string queryString)
{
var nvc = HttpUtility.ParseQueryString(queryString);
return nvc.AllKeys.ToDictionary(k => k, k => nvc[k]);
}
Also, the question asked how to get it back into a query string:
public static string CreateQueryString(Dictionary<string, string> parameters)
{
return string.Join("&", parameters.Select(kvp =>
string.Format("{0}={1}", kvp.Key, HttpUtility.UrlEncode(kvp.Value))));
}
Just had to do this for a mono compatible solution
Regex.Matches(queryString, "([^?=&]+)(=([^&]*))?").Cast<Match>().ToDictionary(x => x.Groups[1].Value, x => x.Groups[3].Value)
In ASP.NET Core, use ParseQuery.
var query = HttpContext.Request.QueryString.Value;
var queryDictionary = Microsoft.AspNetCore.WebUtilities.QueryHelpers.ParseQuery(query);
I like the brevity of Jon Canning's answer, but in the interest of variety, here is another alternative to his answer, that would also work for restricted environments like Windows Phone 8, that lack the HttpUtility.ParseQueryString() utility:
public static Dictionary<string, string> ParseQueryString(String query)
{
Dictionary<String, String> queryDict = new Dictionary<string, string>();
foreach (String token in query.TrimStart(new char[] { '?' }).Split(new char[] { '&' }, StringSplitOptions.RemoveEmptyEntries))
{
string[] parts = token.Split(new char[] { '=' }, StringSplitOptions.RemoveEmptyEntries);
if (parts.Length == 2)
queryDict[parts[0].Trim()] = HttpUtility.UrlDecode(parts[1]).Trim();
else
queryDict[parts[0].Trim()] = "";
}
return queryDict;
}
Actually, a useful improvement to Canning's answer that take care of decoding url-encoded values (like in the above solution) is:
public static Dictionary<string, string> ParseQueryString2(String query)
{
return Regex.Matches(query, "([^?=&]+)(=([^&]*))?").Cast<Match>().ToDictionary(x => x.Groups[1].Value, x => HttpUtility.UrlDecode( x.Groups[3].Value ));
}
One liner without HttpUtility
var dictionary = query.Replace("?", "").Split('&').ToDictionary(x => x.Split('=')[0], x => x.Split('=')[1]);
Yet another way to do it:
NameValueCollection nvcData = HttpUtility.ParseQueryString(queryString);
Dictionary<string, string> dictData = new Dictionary<string, string>(nvcData.Count);
foreach (string key in nvcData.AllKeys)
{
dictData.Add(key, nvcData.Get(key));
}
Most simple:
Dictionary<string, string> parameters = new Dictionary<string, string>();
for (int i = 0; i < context.Request.QueryString.Count; i++)
{
parameters.Add(context.Request.QueryString.GetKey(i), context.Request.QueryString[i]);
}
I stumbled across this post whilst looking for the same solution for an Azure WebJob, hopefully this helps others doing the same.
If you are coding an Azure WebJob you use the GetQueryParameterDictionary() extension method.
var queryParameterDictionary = request.GetQueryParameterDictionary();
where request is of type HttpRequest and queryParameterDictionary is now of type IDictionary<string, string>
You can just get it by decorating the parameter with the FromQueryAttribute
public void Action([FromQuery] Dictionary<string, string> queries)
{
...
}
P.S. If you want to get multiple values for each key you can change the Dictionary to Dictionary<string, List<string>>
Instead of converting HttpContext.Request.QueryString to Dictionary<>, try using
HttpContext.Request.Query
which already is a Dictionary<string, StringValues>
AspNet Core now automatically includes HttpRequest.Query which can be used similar to a dictionary with key accessors.
However if you needed to cast it for logging or other purposes, you can pull out that logic into an extension method like this:
public static class HttpRequestExtensions
{
public static Dictionary<string, string> ToDictionary(this IQueryCollection query)
{
return query.Keys.ToDictionary(k => k, v => (string)query[v]);
}
}
Then, you can consume it on your httpRequest like this:
var params = httpRequest.Query.ToDictionary()
Further Reading
How to parse a query string into a NameValueCollection in .NET
Convert query string to key-value pair in .Net
Is it possible to get Dictionary from query string?