How to write Dictionary contents to a textfile - c#

I have declared a dictionary like below--
Dictionary<int, string> dic = new Dictionary<int, string>()
{
{977,"String1"},
{1021,"String2"},
{784,"String3"},
{801, "String4"}
};
In my textfile value will be contain like this-
977,"String1",
1021,"String2",
784,"String3",
801, "String4"
I want to store above dictionary keys and values manually in a text file and want to access like dictionary by for loop.
Like this--
foreach (KeyValuePair<int, string> pair in dic)
{
if (pair.Key == any_integer_value_to_compare)
{
Console.WriteLine(pair.Value);
}
}
How can I do that??

You can use serialization/De-serialization to store and retrieve dictionary data from a XML file. It's better method as far as performance is concerned.
Here is how you can implement that:
Declare class Item:
public class item
{
[XmlAttribute]
public int id;
[XmlAttribute]
public string value;
}
Your Dictionary:
Dictionary<int, string> dict = new Dictionary<int, string>()
{
{977,"String1"},
{1021,"String2"},
{784,"String3"},
{801, "String4"}
};
Create Serializer object:
XmlSerializer serializer = new XmlSerializer(typeof(item[]),newXmlRootAttribute() { ElementName = "items" });
Serialization:
serializer.Serialize(stream,dict.Select(kv=>new item(){id = kv.Key,value=kv.Value}).ToArray() );
Deserialization:
var myDict = ((item[])serializer.Deserialize(stream)).ToDictionary(i =>i.id, i => i.value);
Accessing your dictionary values
foreach (KeyValuePair<int, string> pair in myDict )
{
if (pair.Key == any_integer_value_to_compare)
{
Console.WriteLine(pair.Value);
}
}
In this way you can systematically store the state of your dictionary values at the particular instance and access it later on by de-serializing the XML file.

To create or override a CSV file (note: there're no spaces and quotes)
977,String1
1021,String2
784,String3
801,String4
you can use Linq
File.WriteAllLines(#"C:\MyTest\MyFile.txt", dic
.Select(pair => String.Join(",", pair.Key, pair.Value)));
If you want to add quotations for values, add them (the simplest implementation)
File.WriteAllLines(#"C:\MyTest\MyFile.txt", dic
.Select(pair => String.Join(",", pair.Key, "\"" + pair.Value + "\"")));
you can't add spaces since line
{801, "String4"},
is totally equals to
{801,"String4"},
In case you want to convert the dictionary into String (and then combine it
with some other text(s) in order ro put into text file):
String text = String.Join(Environment.NewLine, dic
.Select(pair => String.Join(",", pair.Key, pair.Value))

Related

Using Json.NET to convert part of a JObject to Dictionary<string, string>

I'm testing out Json.Net in preparation for a different project, and I'm having some trouble. What I want to do is convert the content of moretests to a Dictionary. Here's my full code:
class Program
{
static void Main(string[] args)
{
string json = #"{
'test': 'a',
'test2': 'b',
'moretests':{
'test3': 'c',
'test4': 'd'
}
}";
JObject parsed = JObject.Parse(json);
IDictionary<string, JToken> results = (JObject)parsed["moretests"];
Dictionary<string, string> results2 = results.ToDictionary(pair => pair.Key, pair => (string)pair.Value);
foreach (var i in results.Keys)
{
Console.WriteLine($"{i}: {results[i]}");
}
}
}
I got these 2 lines:
IDictionary<string, JToken> results = (JObject)parsed["moretests"];
Dictionary<string, string> results2 = results.ToDictionary(pair => pair.Key, pair => (string)pair.Value);
from here but I was wondering if it's possible to shorten it to one line. I tried doing
Dictionary<string, string> results = (JObject)parsed["moretests"].ToDictionary(pair => pair.Key, pair => pair.Value)
but it didn't work as in that case pair is no longer a KeyValuePair but instead a JToken. Can anybody help me out?
You could use this line
Dictionary<string, string> results = ((IDictionary<string, JToken>)(JObject)parsed["moretests"]).ToDictionary(pair => pair.Key, pair => (string)pair.Value);
You may want to avoid doing this though, it really hurts readability.
Edit
I messed around with it for a while and got this cleaner version.
Dictionary<string, string> results = JsonConvert.DeserializeObject<Dictionary<string, string>>(parsed["moretests"].ToString());

Get Values from dictionary present in List

I have a list like,
List<string> list = new List<string>();
list.Add("MEASUREMENT");
list.Add("TEST");
I have a dictionary like,
Dictionary<string, string> dict = new Dictionary<string, string>();
dict.Add("BPGA", "TEST");
dict.Add("PPPP", "TEST");
dict.Add("RM_1000", "MEASUREMENT");
dict.Add("RM_2000", "MEASUREMENT");
dict.Add("CDMA", "TEST");
dict.Add("X100", "XXX");
Now, I want to get all matched data from dictionary based on list.
Means, all data from list match with dict value then get new dictionary with following mathched values
Is there any way to achieve this by using lambda expression?
I want result like this.
Key Value
"BPGA", "TEST"
"PPPP", "TEST"
"RM_1000", "MEASUREMENT"
"RM_2000", "MEASUREMENT"
"CDMA", "TEST"
Thanks in advance!
You should be using the dictionary like it is intended to be used i.e. a common key with multiple values for example:
Dictionary<string, List<string>> dict = new Dictionary<string, List<string>>();
Then all you need to do when adding the values is:
dict.Add("TEST", new List<string>() { /*strings go in here*/ });
Then to get all the results from a key like:
List<string> testValues = dict["TEST"];
To make it safe however you should check that the key exists i.e.
if (dict.ContainsKey("TEST"))
{
//Get the values
}
Then to add values to a current key you go do something like:
dict["TEST"].Add("NewValue");
If you insist on keeping the same structure, although I do not recommend it, something like the following will work:
List<string> testKeys = new List<string>();
foreach (var pairs in dict)
{
if (pair.Value == "TEST")
{
testKeys.Add(pair.Key);
}
}
Or even the following LINQ statement:
List<string> testKeys = dict.Where(p => p.Value == "TEST").Select(p => p.Key).ToList();
For a generic query to find the ones from your list use:
List<string> values = dict.Where(p => list.Contains(p.Value)).ToList();

Alternate of if and foreach for Linq

Could there be a sophisticated LINQ for the following code.
My code is trying to prepare a dictionary of string(key), string(value), by first getting a list of objects from another dictionary and then looping over to that list of objects.
Dictionary<string, string> displayNames = new Dictionary<string, string>();
List<DefDefaultDataSet.dbEnumsRow> enumList;
//allEnums dictionary: Key as string and value as List<DefDefaultDataSet.dbEnumsRow>
//enumID is a string object
if (allEnums.TryGetValue(enumID, out enumList))
{
foreach (DefDefaultDataSet.dbEnumsRow row in enumList)
{
string enumValue = row.Value;
//If already have enumvalue ,no need to add again
if (!string.IsNullOrWhiteSpace(enumValue) && !displayNames.ContainsKey(enumValue))
{
displayNames.Add(enumValue, FindResourceVal(row.ResourceKey, uniqueKey));
}
}
}
You can keep the if statement, then filters using Where and create the dictionary using ToDictinary:
if (allEnums.TryGetValue(enumID, out enumList))
displayNames = enumList.Where(e => !string.IsNullOrWhiteSpace(e.Value) && !displayNames.ContainsKey(e.Value))
.ToDictionary(k => k.ResourceKey, v => FindResourceVal(v.ResourceKey, uniqueKey));

Concat two dictionaries so that original's shared keys are updated

Say I have two dictionaries:
Dictionary<string, string> orig = new Dictionary <string, string>();
orig.Add("one", "value one");
orig.Add("two", "");
orig.Add("three", "");
Dictionary<string, string> newDict = new Dictionary <string, string>();
newDict.Add("one", "this value should not be added");
newDict.Add("two", "value two");
newDict.Add("three", "value three");
How can I merge the two dictionaries so that the resulting dictionary updates the keys only where their corresponding values are empty? Additionally, the merge should not add any keys that are present in new but not in orig. That is, "one" still has the value "value one" while "two" and "three" are updated with the values from new.
I tried using orig.Concat(new);, but that leaves me with the original dictionary. Perhaps this can be done with LINQ?
Try:
orig = orig.Keys.ToDictionary(c => c, c=>(orig[c] == "" ? newDict[c] : orig[c]));
This loop does what you want efficiently and readable:
Dictionary<string, string> result = new Dictionary<string, string>();
foreach (var keyVal in orig)
{
if (!string.IsNullOrEmpty(keyVal.Value))
result.Add(keyVal.Key, keyVal.Value);
else
{
string val2;
if (newDict.TryGetValue(keyVal.Key, out val2))
result.Add(keyVal.Key, val2);
else
result.Add(keyVal.Key, "");
}
}
Result:
one, value one
two, value two
three, value three
I would use the foreach
foreach (var pair in orig.Where(x=> string.IsNullOrEmpty(x.Value)).ToArray())
{
orig[pair.Key] = newone[pair.Key];
}
Extension method 'one-liners' are great when they help to clarify intention, but for something like this, I would be inclined to write a small method with an explicit loop that does the desired operation. I think this is much cleaner than creating a new dictionary using various extension method transformations:
public void PopulateMissingValues(Dictionary<string, string> orig, Dictionary<string, string> newDict)
{
foreach (var pair in orig.Where(p => p.Value == string.Empty))
{
string newValue;
if (newDict.TryGetValue(pair.Key, out newValue))
orig[pair.Key] = newValue;
}
}

Flatten nested Dictionary<string, object>

I am deserializing some nested JSON with the following:
string json = #"{
""name"": ""charlie"",
""someID"": 123,
""level1"" : {
""name"": ""charlie 1"",
""someID"": 456
}
}";
JavaScriptSerializer serializer = new JavaScriptSerializer();
Dictionary<string, object> data = serializer.Deserialize<Dictionary<string, object>>(json);
Once this is done, the values of each dictionary key may be another Dictionary, and so on, multiple levels deep.
What I would like to do is to flatten the multi-level data so it's just a flat Array/List, with just all the JSON attribute names and their values. So that I end up with something like this:
name, "charlie"
someID, 123
name, charlie 1
someID, 456
I was heading down the path of using SelectMany() and so forth, but could not wrangle it to do what I am after.
I've been sort of waddling around with things like this:
var obj = data.Values.SelectMany<object, Dictionary<string, object>>(x => x);
But I am not able to satisfy the compiler. Yes, I am lost.
I am using .NET 3.5.
Func<Dictionary<string, object>, IEnumerable<KeyValuePair<string, object>>> flatten = null;
flatten = dict => dict.SelectMany(kv =>
kv.Value is Dictionary<string,object>
? flatten((Dictionary<string,object>)kv.Value)
: new List<KeyValuePair<string,object>>(){ kv}
);
var flatList = flatten(data).ToList();
You need recursion here:
IEnumerable<Tuple<string, string>> Flatten(this IDictionary dict)
{
foreach(DictionaryEntry kvp in dict)
{
var childDictionary = kvp.Value as IDictionary;
if(childDictionary != null)
{
foreach(var tuple in childDictionary.Flatten())
yield return tuple;
}
else
yield return Tuple.Create(kvp.Key.ToString(), kvp.Value.ToString());
}
}
// Usage:
var flatList = data.Flatten().ToList();
On .NET 3.5, you can use KeyValuePair<string, string> instead of Tuple<string, string>.
Please note that there is no KeyValuePair.Create, you need to use new KeyValuePair<string, string>(kvp.Key.ToString(), kvp.Value.ToString()) instead.

Categories

Resources