I'm new to C# and I'm trying to create an object by looping over a string array:
indexKeys = ["A", "B", C"].
The elements of indexKeys are not known in advance.
I have an Object data, some of whose keys are present in indexKeys:
data = {"A": "string1", "B": "string2", "C": "string3", "D": "string4"}
The final object token must be a serialized form of:
{
"A": {
"S": "string1"
},
"B": {
"S": "string2"
},
"C": {
"S": "string3"
}
}
My code below is surely wrong but I'm confused about the data types in C#.
private string getToken(Object data, string[] indexKeys){
Token token = new Token{};
foreach(string i in indexKeys){
token.Add(i: {S: data[i]});
}
//return serialized token
}
How can I implement getToken to get the desired result?
You can use Dictionary like this:
var dataDictionary = JsonConvert.DeserializeObject<Dictionary<string, string>>(data);
var response = new Dictionary<string, object>();
foreach (var item in dataDictionary)
{
response.Add(item.Key, new { S = item.Value });
}
var json = JsonConvert.SerializeObject(response);
When data is object and using it directly(with reflection):
static string GetToken(object data, IEnumerable<string> indexKeys)
{
var dict = new Dictionary<string, object>();
foreach (var key in indexKeys)
{
dict.Add(key, new { S = data.GetType().GetProperty(key).GetValue(data, null).ToString() });
}
return JsonSerializer.Serialize(dict);
}
static void Main(string[] args)
{
var indexKeys = new List<string>() { "A", "B", "C" };
var data = new { A = "string1", B = "string2", C = "string3", D = "string4" };
var result = GetToken(data, indexKeys);
Console.WriteLine(result);
}
If you supply data as dictionary instead of object:
static string GetToken(Dictionary<string, string> data, IEnumerable<string> indexKeys)
{
var dict = new Dictionary<string, object>();
foreach (var key in indexKeys)
{
dict.Add(key, new { S = data[key] });
}
return JsonSerializer.Serialize(dict);
}
static void Main(string[] args)
{
var indexKeys = new List<string>() { "A", "B", "C" };
var dataDict = new Dictionary<string, string>()
{
{ "A", "string1" },
{ "B", "string2" },
{ "C", "string3" },
{ "D", "string4" }
};
var result = GetToken(dataDict, indexKeys);
Console.WriteLine(result);
}
When data is object but without using reflection:
static string GetToken(object data, IEnumerable<string> indexKeys)
{
var dataDict = JsonSerializer.Deserialize<Dictionary<string, object>>(JsonSerializer.Serialize(data));
var dict = new Dictionary<string, object>();
foreach (var key in indexKeys)
{
dict.Add(key, new { S = dataDict[key] });
}
return JsonSerializer.Serialize(dict);
}
static void Main(string[] args)
{
var indexKeys = new List<string>() { "A", "B", "C" };
var data = new { A = "string1", B = "string2", C = "string3", D = "string4" };
var result = GetToken(data, indexKeys);
Console.WriteLine(result);
}
All of those solutions assume that your data object/dictionary will contain all the keys from indexKeys.
Related
var fruitDictionary = new Dictionary<string, string>(StringComparer.InvariantCultureIgnoreCase) { { "Apple" , "Fruit" }, { "Orange", "Fruit" }, { "Spinach", "Greens" } };
TextRange textRange = new TextRange(richTextBox1.Document.ContentStart, richTextBox1.Document.ContentEnd);
string data = textRange.Text;
var output = new StringBuilder(data);
foreach (var kvp in fruitDictionary)
output.Replace(kvp.Key, kvp.Value);
var result = output.ToString();
richTextBox2.AppendText(result);
It works normally but if the input isnt in format it wont work. For example on Apple the output is Fruit but on apple it still says apple
By setting the dictionary's comparer to StringComparer.InvariantCultureIgnoreCase, key lookup became culture and case invariant -- i.e. var a = fruitDictionary["apple"]; and var b = fruitDictionary["ApPlE"] will yield the same results. That said, you perform your replace operation on an instance of StringBuilder which is not related to that. Both StringBuilder.Replace and String.Replace don't have overloads that let you configure string comparison options, so you would have to make an extension method.
public static string Replace(this string str, string oldValue, string newValue,
StringComparison comparison = StringComparison.Ordinal)
{
var index = str.IndexOf(oldValue, comparison);
while (index >= 0)
{
str = str.Remove(index, oldValue.Length);
str = str.Insert(index, newValue);
index = str.IndexOf(oldValue, comparison);
}
return str;
}
var fruitDictionary = new Dictionary<string, string>(StringComparer.InvariantCultureIgnoreCase) { { "Apple" , "Fruit" }, { "Orange", "Fruit" }, { "Spinach", "Greens" } };
TextRange textRange = new TextRange(richTextBox1.Document.ContentStart, richTextBox1.Document.ContentEnd);
string data = textRange.Text;
foreach (var kvp in fruitDictionary)
data = data.Replace(kvp.Key, kvp.Value, StringComparison.InvariantCultureIgnoreCase)
richTextBox2.AppendText(data);
I am web-scraping some data and trying to write the scraped data to a json file using C# newtonsoft.Json
I get stuck when writing a foreach in my .ToDictionary function as well as not being able to ++ an index into my .ToDictionary function.
My class:
public class JsonParametersData
{
public bool required { get; set; }
public bool list { get; set; }
public List<string> options { get; set; }
}
My arrays
var jsonData = new List<Dictionary<string, Dictionary<string, JsonParametersData>>>();
var moduleParameters = new List<string>();
var parameterOptionsArray = new List<List<string>>();
var parameterOptions = new List<string>();
var requiredArray = new List<bool>();
var listArray = new List<bool>();
string moduleName = item.Attributes["href"].Value.Replace("_module.html", "");
The code which is commented shows what I am trying to do.
int index = 0;
jsonData.Add(new Dictionary<string, Dictionary<string, JsonParametersData>>()
{
{
moduleName,
moduleParameters
.ToDictionary(n => n,
n => new JsonParametersData
{
required = requiredArray[index],
list = listArray[index],
options = new List<string>() { "option1", "option2" },
/*
foreach (var parameteroption in parameterOptionsArray[index])
{
options.Add(parameteroption);
}
index++;
*/
})
}
});
string json = JsonConvert.SerializeObject(jsonData.ToArray());
//write string to file
System.IO.File.WriteAllText(#"path", json);
Your parameterOptionsArray is not an Array, but a List of lists.
The thing is that parameterOptionsArray[index] is a List, not a string. So you should use AddRange() instead of Add().
parameterOptionsArray.Foreach(parameteroption => options.AddRange(parameteroption));
As I´ve written in the comments you can make only assignments in an object-initializer. Thus the following is allowed:
var a = new { MyMember = anInstance }
whilst this is not:
var a = new { MyMember = anInstance, anInstance.DoSomething() };
That´s one of those cases where you should not use Linq at all, as it leads to more confusion than it helps. Instead use a good old-styled loop:
int index = 0;
var innerDict = new Dictionary<string, JsonParametersData>();
foreach(var name in moduleParameters)
{
innerDict[name] = new JsonParametersData
{
required = requiredArray[index],
list = listArray[index],
options = new List<string>() { "option1", "option2" },
}
innerDict[name].Options.AddRange(parameterOptionsArray[index]);
index++;
}
var dict = new Dictionary<string, Dictionary<string, JsonParametersData>>();
dict[moduleName] = innerDict;
jsonData.Add(dict);
string json = JsonConvert.SerializeObject(jsonData.ToArray());
You appear to have a jagged array in parameterOptionsArray. You can make use of SelectMany here. Perhaps following sample can help:
string[][] parameterOptionsArray = new string[2][];
parameterOptionsArray[0] = new string[2];
parameterOptionsArray[0][0] = "1";
parameterOptionsArray[0][1] = "2";
parameterOptionsArray[1] = new string[2];
parameterOptionsArray[1][0] = "3";
parameterOptionsArray[1][1] = "4";
var testing = new {options = parameterOptionsArray.SelectMany(x => x).ToList()};
testing.options.ForEach(x => Console.WriteLine(x));
Given a String that is a Key contained in Dictionary<String, List<String>>, how do I retrieve the KeyValuePair<String, List<String>> that corresponds to that Key?
The problem with other answers using FirstOrDefault is that it will sequentially search the entire dictionary until it finds a match, and you lose the benefit of having a hashed lookup. It seems more sensible if you really need a KeyValuePair to just build one, like this:
public class Program
{
public static void Main(string[] args)
{
var dictionary = new Dictionary<string, List<string>>
{
["key1"] = new List<string> { "1" },
["key2"] = new List<string> { "2" },
["key3"] = new List<string> { "3" },
};
var key = "key2";
var keyValuePair = new KeyValuePair<string, List<string>>(key, dictionary[key]);
Console.WriteLine(keyValuePair.Value[0]);
}
}
(with credit to David Pine for the original code in his answer).
Here's a fiddle for that: https://dotnetfiddle.net/Zg8x7s
Usually you want the value associated with the key, for example:
Dictionary<String, List<String>> dictionary = GetDictionary();
var value = dictionary["key"];
But you can use Linq to get the entire KeyValuePair:
var dictionary = new Dictionary<string, List<string>>
{
["key1"] = new List<string> { "1" },
["key2"] = new List<string> { "2" },
["key3"] = new List<string> { "3" },
};
var keyValuePair = dictionary.FirstOrDefault(kvp => kvp.Key == "key2");
Console.WriteLine(keyValuePair?.Value[0]); // Prints "2"
Here is a .NET Fiddle.
This is my current solution. Any better search algorithms?
public void membersOfBothGroup(string groupA,string groupB)
{
List usersInGroupA = getGroupMembers(groupA);
List usersInGroupB = getGroupMembers(groupB);
List userInBothAB = new List();
foreach (string userA in usersInGroupA)
{
foreach(string userB in usersInGroupB)
{
if (userA == userB)
{
userInBothAB.Add(userA);
}
}
}
}
Here's an example (since the datatype is string):
List<string> groupA = new List<string>() { "Moe", "Larry", "Curly" };
List<string> groupB = new List<string>() { "Moe", "Shemp", "CurlyJoe" };
var result = groupB.Intersect(groupA);
Output:
Moe
How about:
List<string> userinBothAB = usersInGroupA.Intersect(usersInGroupB);
Check the MSDN for more details.
Is it possible to implicitly declare next Dictionary<HyperLink, Anonymous>:
{ urlA, new { Text = "TextA", Url = "UrlA" } },
{ urlB, new { Text = "TextB", Url = "UrlB" } }
so I could use it this way:
foreach (var k in dic)
{
k.Key.Text = k.Value.Text;
k.Key.NavigateUrl = k.Value.Url;
}
?
How about:
var dict = new[] {
new { Text = "TextA", Url = "UrlA" },
new { Text = "TextB", Url = "UrlB" }
}.ToDictionary(x => x.Url);
// or to add separately:
dict.Add("UrlC", new { Text = "TextC", Url = "UrlC" });
However, you could just foreach on a list/array...
var arr = new[] {
new { Text = "TextA", Url = "UrlA" },
new { Text = "TextB", Url = "UrlB" }
};
foreach (var item in arr) {
Console.WriteLine("{0}: {1}", item.Text, item.Url);
}
You only need a dictionary if you need O(1) lookup via the (unique) key.
Yes, but only with great workaround, and only within a method.
This is how you can do it:
static Dictionary<TKey, TValue> NewDictionary<TKey, TValue>(TKey key, TValue value)
{
return new Dictionary<TKey, TValue>();
}
public void DictRun()
{
var myDict = NewDictionary(new { url="a"},
new { Text = "dollar", Url ="urlA"});
myDict.Add(new { url = "b" }, new { Text = "pound", Url = "urlB" });
myDict.Add(new { url = "c" }, new { Text = "rm", Url = "urlc" });
foreach (var k in myDict)
{
var url= k.Key.url;
var txt= k.Value.Text;
Console.WriteLine(url);
Console.WriteLine(txt);
}
}
You can refer to this SO question for more info.