How can I create a truly complicated collection? - collections

Looks like I will never run out of problems. Now I would like to initialize a Dictionary like this( exactly this):
Dictionary<string, Dictionary<int, int>> origRes = new Dictionary<string, Dictionary<int, int>>
Or else I need a collection, which can contains one string and two integer values. And will enough a simple for or foreach loop to collect all these datas( the string can be a key value)?
Update
public static Dictionary<int, int> resRequest(string requestedForm)
{
Dictionary<int, int> kp = new Dictionary<int, int>();
Dictionary<string, KeyValuePair<int, int>> origRes = new Dictionary<string, KeyValuePair<int, int>>();
origRes.Add("Polübiosz", new KeyValuePair<int, int>(560,310));
origRes.Add("Morze", new KeyValuePair<int, int>(690, 510));
origRes.Add("Caesar", new KeyValuePair<int, int>(700, 500));
origRes.Add("OwnCrypt", new KeyValuePair<int, int>(830, 570));
origRes.Add("Hamming", new KeyValuePair<int, int>(850, 500));
origRes.Add("Kezdőkép", new KeyValuePair<int, int>(1280, 1024));
foreach(KeyValuePair<string,KeyValuePair<int, int>> pair in origRes)
{
if(pair.Key==requestedForm)
{
kp.Add(pair.Value.Key,pair.Value.Value);
}
}
return kp;
}
Here is my full method And I want to get the key and the value from the KeyValuePair, but the returned Dictionary doesn't contains it or I don't know, but on the calling side there is no key or value attribute only keys and values.

Why not create a class that contains a string, int, int and populate a simpler dictionary with that?
So instead of
Dictionary<string, Dictionary<int, int>>
Do:
Dictionary<string, MyType>
Where MyType is something like:
class MyType {
public string KeyVal { get; set; } // optional - to match your dict key
public int Int1Val{ get; set; }
public int Int2Val{ get; set; }
}

Related

unity dictionary value return null

i have Dictionary "DebugCommands" in DebugCommandBase
public class DebugCommandBase
{
private string _id;
private string _description;
private string _format;
public static Dictionary<string, DebugCommandBase> DebugCommands;
public DebugCommandBase(string id, string description, string format)
{
if (DebugCommands == null)
DebugCommands = new Dictionary<string, DebugCommandBase>();
string mainKeyword = format.Split(' ')[0];
DebugCommands[mainKeyword] = this;
}
public string Id => _id;
public string Description => _description;
public string Format => _format;
}
new DebugCommand("test_command", "test", "test_command", () =>
{
//any command
});
In general, everything works well, but when I try to get a value from a dictionary, I get null
foreach (DebugCommandBase command in DebugCommandBase.DebugCommands.Values)
{
print(command.Description);
//return null
}
OR
print(DebugCommandBase.DebugCommands["test_command"].Format); //return null
what is the correct way to get the value from such a dictionary?
Did you in fact check the command has a populated Description?
Normally, your approach of accessing the values in a dictionary is correct. A similar opportunity to access the values of a dictionary entry is possible by a slight change of code. You'd access each dictionary entry as a keyvaluepair.
foreach (KeyValuePair<string, DebugCommandBase> dEntry in DebugCommamdBase.DebugCommands)
{
print(dEntry.Value.Description);
}

SmartFormat best way to serialize a dictionary

I have a data object with an dictionary.
Now I want to serialize this dictionary to a json string.
Is it possible to do this inside the template?
public string GenerateTest()
{
Dictionary<string, object> dataDictionary = new Dictionary<string, object>();
dataDictionary.Add("Testdata1", "Value1");
dataDictionary.Add("Testdata2", "Value2");
string result = Smart.Format(CultureInfo.InvariantCulture, "{data.someFormattertoGetAnJsonString}", new {data= dataDictionary });
Console.WriteLine(result);
return result;
}
Sure you could do that, but not in a generic way. SmartFormat is a formatter, rather than a serializer. So in general, SmartFormat is best in filling a text template with data, like it is required with mail merge.
In your case, you'll be better off using serializers like System.Text.Json or Newtonsoft.Json.
For the latter, here is an example how simple this works: https://www.newtonsoft.com/json/help/html/serializedictionary.htm
I have attached my solution. You have to register the ToJSONFormatter with the AddExtensions Method. After that you can call it like this: {MyVariable:ToJSON()}
Smart.Default.AddExtensions(new ToJSONFormatter());
public class ToJSONFormatter : IFormatter
{
public string Name { get; set; } = "ToJSON";
public bool CanAutoDetect { get; set; } = false;
private JsonSerializerSettings JsonSerializerSettings = new JsonSerializerSettings { DateFormatString = "yyyy-MM-ddTHH:mm:ss" };
//{Data:ToJSON()}
public bool TryEvaluateFormat(IFormattingInfo formattingInfo)
{
formattingInfo.Write(JsonConvert.SerializeObject(formattingInfo.CurrentValue));
return true;
}
}

Set the comparer for Newtonsoft.Json.JsonConvert to use for HashSet/Dictionary

I have a HashSet<string> that JsonConvert.SerializeObject serialises to an array.
When I deserialise using JsonConvert.DeserializeObject<HashSet<string>> I get a new HashSet<string> with the same values. However, the Comparer has been reset.
// JSON settings
var settings = new JsonSerializerSettings
{
ContractResolver = new CamelCasePropertyNamesContractResolver()
};
// Create a case insensitive hashset
var h = new HashSet<string>(new string[] {"A", "b"}, StringComparer.OrdinalIgnoreCase);
h.Contains("a"); // TRUE
// Serialise and deserialise with Newtonsoft.Json
string s = JsonConvert.SerializeObject(h, settings);
// s = ["A", "b"]
var newH = JsonConvert.DeserializeObject<HashSet<string>>(s, settings);
// Result is now case-sensitive
newH.Contains("a"); // FALSE
newH.Contains("A"); // TRUE
This is because JsonConvert uses EqualityComparer<string>.Default, which is case sensitive.
How do I tell it to use StringComparer.OrdinalIgnoreCase instead?
I don't want to include the HashSet<string>.Comparer property in the serialised data (I think it should be a simple array in JSON), I want to specify it at the point of deserialisation.
You could use JsonConvert.PopulateObject() instead, when the hash set is the root object:
var newH = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
JsonConvert.PopulateObject(s, newH);
When the hash set is not the root object, Json.NET will populate it if preallocated unless ObjectCreationHandling.Replace is enabled. This allows the containing type to pre-allocate the hash set with the required comparer, e.g.:
public class RootObject
{
public RootObject() { this.Collection = new HashSet<string>(StringComparer.OrdinalIgnoreCase); }
public HashSet<string> Collection { get; private set; }
}
Alternatively, you could subclass CustomCreationConverter<HashSet<T>> and allocate the hash set with the required comparer within the converter's Create() method:
public class HashSetCreationConverter<T> : CustomCreationConverter<HashSet<T>>
{
public IEqualityComparer<T> Comparer { get; private set; }
public HashSetCreationConverter(IEqualityComparer<T> comparer)
{
this.Comparer = comparer;
}
public override HashSet<T> Create(Type objectType)
{
return new HashSet<T>(Comparer);
}
}
And then do:
var newH = JsonConvert.DeserializeObject<HashSet<string>>(s, new HashSetCreationConverter<string>(StringComparer.OrdinalIgnoreCase));

Create JSON object or string..?

Can we initialize JSON object with a string in C# ;
like: "Person": [{"age":"42","name":"John"}]
as object JsonData = "Person": [{"age":"42","name":"John"}];
???
So that i can give this JSON object directly to the DatacontractJSONSerializer
And i could get the data out of it.!
List<Person> people = new List<Person>{
new Person{age = 1, name = "Scott"},
new Person{age = 2, name = "Bill"}
};
string jsonString = ExtensionMethods.JSONHelper.ToJSON(people);
}
}
}
namespace ExtensionMethods
{
public static class JSONHelper
{
public static string ToJSON(this object obj)
{
JavaScriptSerializer serializer = new JavaScriptSerializer();
return serializer.Serialize(obj);
}
public static string ToJSON(this object obj, int recursionDepth)
{
JavaScriptSerializer serializer = new JavaScriptSerializer();
serializer.RecursionLimit = recursionDepth;
return serializer.Serialize(obj);
}
}
}
So,
string jsonString = ExtensionMethods.JSONHelper.ToJSON(people);
Gives a string of : [{},{}]
Empty data structure, Any idea..?
With extension methods, you want to patch your method onto the type that you intend to call that method against. In this case, IEnumerable is a good place to add methods you want to use on a List:
public class Person {
public int age { get; set; }
public string name { get; set; }
}
public static class JSONHelper {
public static string ToJSON(this IEnumerable obj) {
return new JavaScriptSerializer().Serialize(obj);
}
}
void Main() {
List<Person> people = new List<Person> {
new Person() { age = 1, name = "Scott" },
new Person() { age = 2, name = "Bill" }
};
// [{"age":1,"name":"Scott"},{"age":2,"name":"Bill"}]
string json = people.ToJSON();
}
The important distinction is that you should use the extension method against a variable of the type it's defined against. You shouldn't reference the extension method directly.

Traverse a list and retrieve a specified value from List<> in asp.net/c#

I have a list which is defined as
List<SoftwareTitles> softwareTitlesList = new List<SoftwareTitles>();
and the SoftwareTitles is a class which is defines as follows:
public class SoftwareTitles
{
string softwareTitle;
string invoiceNumber;
public SoftwareTitles(string softwareTitle, string invoiceNumber)
{
this.softwareTitle = softwareTitle;
this.invoiceNumber = invoiceNumber;
}
string InvoiceNumber
{
get
{
return this.invoiceNumber;
}
}
string SoftwareTitle
{
get
{
return this.softwareTitle;
}
}
}
And now I'm adding the values from the sql server database to the list defines as follows:
public List<SoftwareTitles> SoftwareListRetrieve()
{
ConnectionToSql con1 = new ConnectionToSql();
string connectionString = con1.ConnectionStringMethod();
SqlConnection sqlConnection = new SqlConnection(connectionString);
SqlCommand cmd2 = new SqlCommand("SelectionOfSoftwareTitles", sqlConnection);
cmd2.CommandType = CommandType.StoredProcedure;
sqlConnection.Open();
SqlDataReader dr2 = cmd2.ExecuteReader();
if (dr2.HasRows)
{
while (dr2.Read())
{
String softwareTitle = (String)dr2[0];
String invoiceNumber = (String)dr2[1];
SoftwareTitles s1 = new SoftwareTitles(softwareTitle, invoiceNumber);
softwareTitlesList.Add(s1);
}
}
sqlConnection.Close();
dr2.Close();
return softwareTitlesList;
}
I want to find out the software title for every occurence of invoice number by looping through List<>. And I don't know how ? I have tried to loop through the List<> by the following code. I wanted to use something like contains i.e., softwareTitlesList[i].contains but seems like there is no such property or method
for(int i=0; i<softwareTitlesList.Count;i++)
{
softwareTitlesList[i]. [BUT IT IS NOT SUGGESTING ME ANYTHING]
}
I'm stuck with this from morning. I don't how to solve this dilemma.
Please help me
Thanks in anticipation
search for an invoice number
string invoiceNumber = "111111111";
using linq
IList<string> titles = softwareTitlesList
.Where(st => st.InvoiceNumber == invoiceNumber)
.Select(st => st.SoftwareTitle);
or
IList<string> titles = softwareTitlesList
.Where(st => st.InvoiceNumber.Contains(invoiceNumber))
.Select(st => st.SoftwareTitle);
w/o using linq, it's still pretty basic
IList<string> titles = new List<string>();
foreach(var softwareTitle in softwareTitlesList)
{
if (softwareTitle.InvoiceNumber.Contains(invoiceNumber))
titles.Add(softwareTitle.SoftwareTitle);
}
you could also rewrite your class like this:
public class SoftwareTitles
{
public SoftwareTitles(string softwareTitle, string invoiceNumber)
{
SoftwareTitle = softwareTitle;
InvoiceNumber = invoiceNumber;
}
public string InvoiceNumber { get; private set; }
public string SoftwareTitle { get; private set; }
}

Resources