Working on a application which reads some values from an customers.xml file to UI.
Linq to xml code:
var Settings = (from e in customer.Descendants("appSettings")
from kvpair in e.Elements("Name")
select new
{
Name = kvpair.Attribute("Zip").Value,
Node = kvpair
}).ToDictionary(x => x.Name, y => y);
txtFName.Text==Settings["CustomerA"].Node.attribute("value").Value;
txtLName=Settings["CustomerB"].Node.attribute("value").Value;
I am able to get the values into GUI from XMl file by the above code.
My question is when i comment out any element or data from xml file of a particular customer i get the error "the given key is not present in the dictionary"
How do i dynamically check whether a key exists in dictionary if then only read that value or else got to the next value ?
You're looking for the ContainsKey() or TryGetValue() methods.
The 'proper' way to check whether a key is present in a Dictionary is to use the ContainsKey function. dictionary.ContainsKey(keyValue);
However, you may want to ask yourself why the key isn't there and whether it should be there.
if (Settings.ContainsKey("CustomerA"))
{
txtLName.Text = Settings["CustomerA"].Node.attribute("value").Value;
}
EDIT:
You can loop through keys accessing Keys property collection:
foreach (var key in Settings.Keys)
{
// ..
}
Also you can use LINQ to filter out what you need:
IList<string> filteredKeys = new List<string> { "A", "B" };
Settings.Where(kv => filteredKeys.Contains(kv.Key));
Related
I'm reading a csv file that contains abbreviations and the full version for example LOL,Laughing out Loud. I've created a dictionary where the abbreviation is the key and full version is the value.
'''
private void btnFilter_Click(object sender, RoutedEventArgs e)
{
var keys = new List<string>();
var values = new List<string>();
using (var rd = new StreamReader("textwords.csv"))
{
while (!rd.EndOfStream)
{
var splits = rd.ReadLine().Split(',');
keys.Add(splits[0]);
values.Add(splits[1]);
}
}
var dictionary = keys.Zip(values, (k, v) => new { Key = k, Value = v }).ToDictionary(x => x.Key, x => x.Value);
foreach (var k in dictionary)
{
//
}
aMessage.MessageContent = txtContent.Text;
}
'''
I'm using a button that will check if the textbox txtContent contains any of the abbreviations in the text and change this to the full version. So if the textbox contained the following. "Going to be AFK" after the button click it would change this to "Going to be away from keyboard".
I want to write a foreach loop that would check for any abbreviations, elongate them and then save this to a string variable MessageContent.
Would anyone be able to show me the best way to go about this as I'm not sure how to do this with the input from a textbox?
Thanks
You can just use LINQ to read and create a dictionary object:
var dictionary = File.ReadAllLines(#"textwords.csv")
.Select(x => x.Split(",",StringSplitOptions.RemoveEmptyEntries))
.ToDictionary(key => key.FirstOrDefault().Trim(),
value => value.Skip(1).FirstOrDefault().Trim());
If the abbrevs are correct, i.e. you don't need fuzzy logic, you can use a variety of .NET objects and search the keys rather quickly.
if(dict.ContainsKey(myKey))
{
}
I did that freehand, so it might be dict.Keys.Contains() or similar. The point is you can search the dictionary directly rather than loop.
If you need to do a more fuzzy search, you can utilize LINQ to write queries to iterate over collections of objects extremely fast (and few lines).
As for yours, you would iterate over dictionary.Keys to seach keys, but I still don't see why you need the extra code.
I have a dictionary containing keys, e.g.
"Car"
"Card Payment"
I have a string description, e.g. "Card payment to tesco" and I want to find the item in the dictionary that corresponds to the string.
I have tried this:
var category = dictionary.SingleOrDefault(p => description.ToLowerInvariant().Contains(p.Key)).Value;
This currently results in both "Car" and "Card Payment" being returned from the dictionary and my code blows up as I have SingleOrDefault.
How can I achieve what I want? I thought about prefixing and suffixing the keys in spaces, but I'd have to do the same to the descriptions - I think this would work but it is a bit dirty. Are there any better ways? I have no objections of changing the Dictionary to some other type as long as performance is not impacted too much.
Required Result for above example: only get "Card Payment"
You can try to use linq OrderByDescending and Take after your where condition. to find the most match word value.
var category = dictionary
.Where(p => description.ToLowerInvariant().Contains(p.Key.ToLowerInvariant()))
.OrderByDescending(x => x.Key.Length)
.Take(1);
c# online
I would use List<string> to contain your keys, because there isn't any reason need to use a key and value collection.
List<string> keys = new List<string>();
keys.Add("Car");
keys.Add("Card Payment");
string description = "Card payment to tesco";
var category = keys
.Where(p => description.ToLowerInvariant().Contains(p.ToLowerInvariant()))
.OrderByDescending(x => x.Length)
.Take(1)
.FirstOrDefault();
NOTE
OrderBy key values length desc can make sure which key is the most match word value.
Here I'm using List<string> keys and System.Text.RegularExpressions find desired key.Try it.
string description = "Card payment to tesco";
List<string> keys = new List<string> {
{"Car" }, {"Card Payment" }
};
string desc = description.ToLowerInvariant( );
string pattern = #"([{0}]+) (\S+)";
var resp = keys.FirstOrDefault( a => {
var regx = new Regex( string.Format( pattern, a.ToLowerInvariant( ) ) );
return regx.Match( desc ).Success;
} );
Check here .NET Fiddle
You are abusing dictionaries. You will get no performance gain from dictionaries by scanning the keys. Even worse, a simple list would be faster in this case. Dictionaries approach a constant time access (O(1)) if you look up a value by the key.
if (dictionary.TryGetValue(key, out var value)) { ...
To be able to use this advantage you will need a more subtle approach. The main difficulty is that sometimes keys might consist of more than a single word. Therefore I would suggest a two level approach where at the first level you store single word keys and at the second level you store the composed keys and values.
Example: Key value pairs to be stored:
["car"]: categoryA
["card payment"]: categoryB
["payment"]: categoryC
We build a dictionary as
var dictionary = new Dictionary<string, List<KeyValuePair<string, TValue>>> {
["car"] = new List<KeyValuePair<string, TValue>> {
new KeyValuePair("car", categoryA)
},
["card"] = new List<KeyValuePair<string, TValue>> {
new KeyValuePair("card payment", categoryB)
},
["payment"] = new List<KeyValuePair<string, TValue>> {
new KeyValuePair("card payment", categoryB),
new KeyValuePair("payment", categoryC)
}
};
Of course, in reality, we would do this using an algorithm. But the point here is to show the structure. As you can see, the third entry for the main key "payment" contains two entries: One for "card payment" and one for "payment".
The algorithm for adding values goes like this:
Split the key the be entered into single words.
For each word, create a dictionary entry using this word as main key and store a key value pair in a list as dictionary value. This second key is the original key possibly consisting of several words.
As you can imagine, step 2 requires you to test whether an entry with the same main key is already there. If yes, then add the new entry to the existing list. Otherwise create a new list with a single entry and insert it into the dictionary.
Retrieve an entry like this:
Split the key the be entered into single words.
For each word, retrieve the existing dictionary entries using a true and therefore fast dictionary lookup(!) into a List<List<KeyValuePair<string, TValue>>>.
Flatten this list of lists using SelectMany into a single List<KeyValuePair<string, TValue>>
Sort them by key length in descending order and test whether the description contains the key. The first entry found is the result.
You can also combine steps 2 and 3 and directly add the list entries of the single dictionary entries into a main list.
I have a dictionary and I want to retrieve all the values list from the dictionary based on a condition on the key, i.e. I want to retrieve only the values for which the respective key matches in alist.
Example: dictionary is as follows
IDictionary<string, string> maskingValues = new Dictionary<string, string>();
maskingValues.Add("cat", "Me#ena");
maskingValues.Add("dog", "N&avya");
maskingValues.Add("llama", "vivek!a");
maskingValues.Add("iguana", "sh^ams");
and I have list of strings as
List<string> keysString = new List<string>();
keysString.Add("cat");
keysString.Add("fox");
Now my requirement is to get the values list from the dictionary where the key matches from the keysString list.
The output should be
Me#ena
till now what I have done is
var all_parameters = maskingValues .Keys.ToList();
var parameters_to_mask = all_parameters.Intersect(keysString);
var values_list = parameters_to_mask.Where(k => data_dictionary.ContainsKey(k)).Select(k => data_dictionary[k]);
so values_list will contain the output Me#ena, I retrieved all the keys from the dictionary and then compared the keys list with the keysString list and then retrieved the values list from the output of the two list's intersect. But can I do it in more optimized way so that the code and the performance is good.
Thanks in advance. Please help me out.
This should work:
var q = maskingValues.Where(x => keysString.Contains(x.Key)).Select(x => x.Value);
foreach (var item in q)
{
Console.WriteLine(item);
}
There are a lot of solutions. This one for example:
var newlist = maskingValues.Where(x => keysString.Contains(x.Key)).Select(y=>y.Value).ToList();
I came up with a quick bit of code to do this fully using linq.
keysString.Where(x => maskingValues.Keys.Contains(x)).ToList().ForEach(x => Console.WriteLine(maskingValues[x]));
Not sure I got the spec right but this is faster than linq:
var matches = new List<string>();
foreach (var key in keysString)
{
if (maskingValues.TryGetValue(key, out string value))
{
matches.Add(value);
}
}
If your dictionary is large, you can improve performance by taking advantage of the fact that accessing an element by key in a dictionary is O(
var result = keysString
.Select(k =>
{ string value;
maskingValues.TryGetValue(k, out value);
return value;
})
.Where(v => v != null);
... etc ...
Note that using TryGetValue is more efficient than calling Contains then the dictionary indexer.
This Should Work:
Below Solution is used when you know your Key name and want to retrive value of key
string objectValue;
maskingValues.TryGetValue("cat", out objectValue);
If you want to Retrive All values from Dictionary than used single line of code: maskingValues.Values
I have a dictionary that gets built which is below
Dictionary<string, string> GTNMobilelist = new Dictionary<string, string>();
GTNMobilelist = LoadMobileNumbers();
i then need to query the Dictionary to check if a mobile number that has been enetered in to a textbox exists within the dictionary "Hope that makes sense" :-/
this is what i have
foreach (GridViewRow HandSetRow in grdvHandSets.Rows)
{
TextBox txtmobileNumber = (TextBox)HandSetRow.FindControl("txtmobilenumber");
//I need the linq statement here if the mobile number doesnt exists i need to
//throw an error saying mobile number doesnt exist within the dictionary
//iv been looking at linq statements for the past hour and im confused :(
}
Can any one help me on a quick solution for this?
There is no point using LINQ here. Use ContainsKey or ContainsValue instead.
if (!GTNMobilelist.ContainsValue(txtmobileNumber.Text))
ShowErrorMessage();
Next time, post your code so far, then we can point out any errors.
It is not clear to me if the phone number is in the key or in the value, but something like this should work.
Check by key:
string phoneNumberToLookFor = "12345678";
bool phoneNumberExists = GTNMobilelist.Any(kvp => kvp.Key == phoneNumberToLookFor);
Or, check by value:
string phoneNumberToLookFor = "12345678";
bool phoneNumberExists = GTNMobilelist.Any(kvp => kvp.Value == phoneNumberToLookFor);
Newbie to C# here....
I have the following code:
var xdoc = XDocument.Parse(xml);
var result = xdoc.Root.Elements("item")
.Select(itemElem => itemElem.Elements().ToDictionary(e => e.Name.LocalName, e => e.Value))
.ToList();
but when I try to use result as I would any List object, such as result.Item, it doesn't work.
What am I doing wrong? Why is result not coming back as a normal List object that I can manipluate in my code? Do I need to make another List object from it?
I am just trying to get the first Dictionary item out of the List and use it.
It depends on what you expected. Your code currently produces a List<Dictionary<string,string>>. So each entry in the list would be a dictionary.
You can access each dictionary as you usually would access list elements, i.e.
string firstResult = result[0]["key"];
The first part [0] is the indexer of the list the second part ["key"] is the indexer of the dictionary - this would return the value for the key "key" of the first dictionary in your list.
This assumes the list has at least one entry though for which you would have to check.
This is a List<Dictionary<String, String>>. Each element in the list is a Dictionary.
It would help to know what you wanted to do with it.
But some examples are:
//Get the First Dictionary Item, then Iterate through all the items in the first dictionary.
var firstItem = results.First();
foreach(var kvPair in firstItem)
{
var key = kvPair.Key;
var val = kvPair.Value;
}
//Loop through each Dictionary getting values from each.
foreach (var result in results)
{
var wordValue = result["word"];
var defValue = result["def"];
}
//Create a list of all the values for the Elements with the key "word".
var valuesForAllWords =
results
.Select(r => r["word"])