Converting a dictionary key in double - c#

I think it is not complicated but after doing some research I can't find an answer to a simple problem.
I am iterating through keys in a dictionary and I would like to use the key which is a string as a double in some calculation.
If I do this :
foreach (KeyValuePair<string, List<string> price in dictionary)
double ylevel = Convert.ToDouble(price.Key);
It seems to not work and I get a "Input string was not in a correct format" error.
What is the right way to get a double from the key..
Thanks
Bernard

You're doing it correctly.
The error message indicates that one of your keys is not actually a double.
If you step through this example in a debugger, you'll see it fails on the second item:
var dictionary = new Dictionary<string, List<string>>();
dictionary.Add("5.72", new List<string> { "a", "bbb", "cccc" });
dictionary.Add("fifty two", new List<string> { "a", "bbb", "cccc" });
foreach (KeyValuePair<string, List<string>> price in dictionary)
{
double ylevel = Convert.ToDouble(price.Key);
}
Solution
To resolve this problem, you should use the following code:
var dictionary = new Dictionary<string, List<string>>();
dictionary.Add("5.72", new List<string> { "a", "bbb", "cccc" });
dictionary.Add("fifty two", new List<string> { "a", "bbb", "cccc" });
foreach (KeyValuePair<string, List<string>> price in dictionary)
{
double ylevel;
if(double.TryParse(price.Key, out ylevel))
{
//do something with ylevel
}
else
{
//Log price.Key and handle this condition
}
}

This is telling you that the string (that happens to be the key, although this is unrelated to the problem) cannot be parsed into a double. Check the value of the string you are attempting to convert.

double ylevel = Convert.ToDouble(price.Key.GetHashCode());

Related

Adding Data in List inside a Dictionary in C#

In Step 1 I wrote this code to access pre-existing list & add value in it .
In Step 2 I updated the dictionary with new list.
In Step 3 again I have to access the list inside dictionary to print the result.
Is there any process or shortcut to add new values to this pre-existing list directly inside dictionary without updating it?
Only have to write the code inside Main. Rest was hardcoded in the compiler & can't be changed.
Your Help will be appreciated. Suggestions are welcome :)
using System;
using System.Collections.Generic;
namespace AddNewMember
{
public class Club
{
static Dictionary<int, string> groupInfo = new Dictionary<int, string>() { { 1, "Gold" }, { 2, "Silver" }, { 3, "Platinum" } };
static Dictionary<int, List<String>> memberInfo = new Dictionary<int, List<String>>() {
{ 1, new List<string>(){ "Tom","Harry"} },
{ 2,new List<string>(){ "Sam","Peter"} },
{ 3,new List<string>(){ "Kim","Robert"} } };
public static void Main(string[] args)
{
//Write your code here. Above part is hardcoded can't be changed
Console.WriteLine("Group Name :");
string gName = Console.ReadLine();
int num = 0;
foreach (KeyValuePair<int, string> VARIABLE in groupInfo)
{
if (VARIABLE.Value == gName)
{
num = VARIABLE.Key;
}
}
Console.WriteLine("Member Name:");
string name = Console.ReadLine();
//Step 1
List<string> l = memberInfo[num];
l.Add(name);
//Step 2
memberInfo[num] = l;
//Step 3
List<string> r = memberInfo[num];
foreach (var VARIABLE in r)
{
Console.WriteLine(VARIABLE);
}
}
}
}
Seems to me like your understanding of dictionaries is upside down. You use the key to retrieve the value, not the other way round. If you're looking to have the user enter a group name (gold, silver, bronze) and then the name of the person to add to that group, you should make the dictionary map a string (group name) to a list of members
static Dictionary<string, List<String>> groupInfo = new() {
{ "Gold", new(){ "Tom","Harry" } },
{ "Silver", new(){ "Sam","Peter"} },
{ "Platinum", new(){ "Kim","Robert"} }
};
public static void Main(string[] args)
{
Console.WriteLine("Group Name :");
string gName = Console.ReadLine();
Console.WriteLine("Member Name :");
string mName = Console.ReadLine();
groupInfo[gName].Add(mName);
}
Yep, that's it. GroupInfo maps string group names to list of string member names, calling groupInfo[gName] resolves to a List of string, so the Add method call there is being performed on the list and the given member name is added
Side note, I'm leveraging a facility of recent c# where you don't have to repeat the type name on both sides of the =. The compiler will know that groupInfo is a Dictionary<string, List<string>> and when it seems new() in the initializer it knows I mean new List<string> which can really help tidy things up. The parentheses are necessary otherwise it would think I was trying to make an anonymous type, which is a different thing. If you get compiler errors you might have to restore the type names if your c# is older
We don't need to re-assign modified list into dictionary value. Step #2 is redundant. When you retrieve the list from step #1. It return a pointer (reference) to the list in the dictionary. It means, when you perform insert an item into the list variable, the list in dictionary is updated (new item added).
Also, In step #3, you get the r but not used.

Iterate a list and keep an index based on the name of the item

I have a list of items which have names and I need to iterate them, but I also need to know how many times this item with the same name it is. So this is an example:
-----
|1|A|
|2|B|
|3|C|
|4|C|
|5|C|
|6|A|
|7|B|
|8|C|
|9|C|
-----
So, when I'm iterating and I'm on row 1, I want to know it is the first time it is an A, when I'm on row 6, I want to know it is the second time, when I'm on row 9, I want to know it is the 5th C, etc. How can I achieve this? Is there some index I can keep track of? I was also thinking of filling a hash while iterating, but perhaps thats too much.
You can use Dictionary<char, int> for keeping count of each character in your list
here your key will be character and value will contain number of occurrences of that character in list
Dictionary<char, int> occurances = new Dictionary<char, int>();
List<char> elements = new List<char>{'A', 'B','C','C','C','A','B', 'C', 'C'};
int result = 0;
foreach(char element in elements)
{
if(occurances.TryGetValue(element, out result))
occurances[element] = result + 1;
else
occurances.Add(element, 1);
}
foreach(KeyValuePair<char, int> kv in occurances)
Console.WriteLine("Key: "+ kv.Key + " Value: "+kv.Value);
Output:
Key: A Value: 2
Key: B Value: 2
Key: C Value: 5
POC: dotNetFiddler
Use dictionary to keep track of counter.
List<string> input = new List<string> { "A", "B", "C", "C", "C", "A", "B", "C", "C" };
Dictionary<string, int> output = new Dictionary<string, int>();
foreach(var item in input)
{
if (output.ContainsKey(item))
{
output[item] = output[item] + 1;
}
else
{
output.Add(item, 1);
}
}
I think you'll need a reversed index instead of row store index.
Row store index just like your table described, and reversed index store terms to search indexes.
Probably like this:
A 1,6
B 2,7
C 3,4,5,8,9
The search engine such like 'Elastic search/Solr' will store terms like this.
If you are in C#, Dictionary<string, List<int>> is pretty much good for you. There you can keep your data that is reverse indexed.
The clean way is to implement your own list; the item is your own object. By this method, you implement your own Iterator pattern with an additional property in your object and your own Add() method. The new Iterator should inherit List and should override the Add() method of List.
I implement this for my own. you can use it. keep in mind, this solution is one of some solutions that exist. However, I think this is one the best solutions with respect to SOLID and OO principals.
public class CounterIterator : List<Item>
{
public new void Add(Item item)
{
base.Add(item);
foreach (var listItem in this)
{
if (listItem.Equals(item))
{
item.CountRepeat++;
}
}
}
}
public class Item
{
public Item(string value)
{
Value = value;
}
public string Value { get; private set; }
public int CountRepeat { get; set; }
public override bool Equals(object obj)
{
var item = obj as Item;
return item != null && Value.Equals(item.Value);
}
}
I tested the code above. It is an extension of List which has an added behavior. If anyone thinks it is not a correct answer, please mention me in comments. I will try to clarify the issue.

Check substring key exists in word and return value

I'm trying to find the most time efficient way of classifying expenses on a piece of Accounting Software. The values come in like this:
"EFTPOS Kathmandu 2342342"
I have created a method as follows:
private static string Classifier(string inputDescription)
{
Dictionary<string, string> classified = new Dictionary<string, string>();
classified.Add("D/C FROM", "INCOME" );
classified.Add("CREDIT ATM", "INCOME");
classified.Add("INTEREST", "INCOME");
classified.Add("EFTPOS", "EXPENSE" );
classified.Add("DEBIT DEBIT", "EXPENSE");
classified.Add("CC DEBIT", "EXPENSE");
classified.Add("PAYMENT RECEIVED", "TRANSFER");
classified.Add("PAYMENT - THANK YOU", "TRANSFER");
classified.Add("IRD", "TAX" );
classified.Add("I.R.D", "TAX");
try
{
// What do I do here to get the value?
return value;
}
catch(Exception)
{
return "OTHER";
}
}
Basically, I want to run through the values of my inputDescription against the keys in the dictionary to get its value (the classification of the line item).
So for the example shown above, the result would be "EXPENSE".
I assumed dictionary would be the fastest way to approach this, but open to suggestions on better methods.
Thanks in Advance!
What about using RegEx?
const string EXPENSE_PATTERN = "^(EFTPOS|DEBIT DEBIT|CC DEBIT)"
const string ..._PATTERN
if (Regex.IsMatch(input, EXPENSE_PATTERN)){
return "EXPENSE";
} else if (Regex.IsMatch(input, INCOME_PATTERN)){
return "INCOME";
} else if (Regex.IsMatch(input, ..._PATTERN)){
return "...";
} else {
return "OTHER"
}
One of the way to achieve this is
string input = "EFTPOS Kathmandu 2342342";
string value = string.Empty;
foreach (var key in input.Split(' '))
{
value = classified.Where(k => classified.ContainsKey(k.Key)).Select(k => classified[k.Key]).FirstOrDefault();
if(value != null & value.trim()!= string.empty)
break;
}
Check the value is null or not for further use. foreach loop will break once will find value.
Calling method:
static void Main(string[] args)
{
Console.WriteLine(Classifier("EFTPOS Kathmandu 2342342"));
Console.WriteLine(Classifier("D/C FROM Kathmandu 2342342"));
Console.ReadKey();
}
Classifier method:
private static string Classifier(string inputDescription)
{
var classified = new Dictionary<string, string>
{
{ "D/C FROM", "INCOME" },
{ "CREDIT ATM", "INCOME" },
{ "INTEREST", "INCOME" },
{ "EFTPOS", "EXPENSE" },
{ "DEBIT DEBIT", "EXPENSE" },
{ "CC DEBIT", "EXPENSE" },
{ "PAYMENT RECEIVED", "TRANSFER" },
{ "PAYMENT - THANK YOU", "TRANSFER" },
{ "IRD", "TAX" },
{ "I.R.D", "TAX" }
};
try
{
foreach (var kvp in classified)
if (inputDescription.StartsWith(kvp.Key))
return kvp.Value;
return "OTHER";
}
catch
{
return "OTHER";
}
}
Returns:
EXPENSE
INCOME
Of course you could move the Dictionary definition outside of the method and make it a class member. That would especially make sense if you have multiple frequent calls to Classifier. You could also define it as an IReadOnlyDictionary to prevent changes to its contents.
The easiest way to get something from a dictionary is by using the key like:
Dictionary<string, string> classified = new Dictionary<string, string>();
var value = classified[key];
but of-course you would wanna check for the key occurence in dictionary like:
if(classified.ContainsKey(key))
return classified[key];
else
throw new InvalidTypeException();//this is because you should have all the key's mapped i.e you are only expecting known key types.People prefer other types like they would return null but i throw coz my dictionary is not having this key
Now coming to the values:
All the Values seem to be known and repeated types.So i would build an enum:
enum TransactionType
{
Expense,
Income,
Transfer
}
enum Source
{
EFTPOS,
DEBIT DEBIT,
...so on...
}
i prefer enums to avoid magic strings and people do make mistakes while typing strings.
So with the Combination of Dictionary and enum now i would build as :
private Dictionary<Source,TransactionType> PopulateSource()
{
Dictionary<Source,TransactionType> classified = new Dictionary<Source,TransactionType>();
//populate dictionary by iterating using
var keys = Enum.GetValues(typeof(Source));
var values = Enum.GetValues(typeof(TransactionType));
you can just iterate through keys if your keys and values in enum are in order .
return classified ;
}
public void TestSourceTransaction()
{
TransactionType transType;
var classifieds = PopulateSource();
var key = GetSourceType(inputDescription);//you need to write a method to get key from desc based on regex or string split options.
if(classifieds.ContainsKey(key))
classifieds[key].Value;
else
throw new InvalidTypeException("Source type undefined");
}
I prefer clean and expandable code and absolute no to magic string.

How to insert an list one by one(Looping over forl loop) to a dictionary of list in c#

I am looping over list and appending the dictionary of list in c# but it appends only the last value of forloop
class Crawl
{
public void SomeFunction()
{
string[] arr1 = new string[] { "one", "two", "three" };
var variations_hash = new Dictionary<string, List<string>>();
foreach(var item1 in arr1)
{
variations_hash["v_id_1"] = item1;
}
foreach (var job in variations_hash)
{
foreach (string jobs in job.Value)
{
Console.Write (jobs+"\n");
}
}
}
. . .
}
Result:
three
Expected result:
one
two
three
How to append all for loop values one by one(as a list/Array) to dictionary(variations_hash)
Expected structure will be
{"v_id_1":"["one","two","three"]"}
You should
Add new key value pair if key doesn't exist
Add new item to the corresponding value if key exists
Let´s just see what should go on:
item1 is "one", there's no key "v_id_1" so we add a pair: {"v_id_1", ["one"]};
item1 is "two", there is a key "v_id_1" and we add to the corresponding value {"v_id_1", ["one", "two"]};
finally, item1 is "three", there is a key "v_id_1" and once again we add to the corresponding value {"v_id_1", ["one", "two", "three"]};
Implementation could be something like this:
string[] arr1 = new string[] { "one", "two", "three" };
var variations_hash = new Dictionary<string, List<string>>();
foreach(var item1 in arr1) {
List<String> list;
if (variations_hash.TryGetValue("v_id_1", out list))
list.Add(item1);
else
variations_hash.Add("v_id_1", new List<String>() {item1});
}
...
You just need to assign the whole array to the dictionary instead of looping through it.
variations_hash["v_id_1"] = arr1.ToList();
Rather than give you a working code sample, I thought I'd just point you in the right direction.
Since you want a Dictionary with a List as the value, it's easier to think in reverse order. Try getting your List ready first and then adding that List into the Dictionary at the end.
You should notice that you keep resetting the value of your Dictionary with a single item. Since Dictionaries are generic, it doesn't know that you want to append the new value to the value that is currently there. This is why I find it easier to work backwards and then it should fall into place easily.
the first foreach is your problem, you are setting the value of v_id_1 three times instead of adding all three values, try:
string[] arr1 = new string[] { "one", "two", "three" };
var variations_hash = new Dictionary<string, List<string>>();
variations_hash["v_id_1"] = arr1.ToList();
foreach (var job in variations_hash)
{
foreach (string jobs in job.Value)
{
Console.Write(jobs + "\n");
}
}

Get the value from list

I create the list like
var list = new List<KeyValuePair<string, string>>();
list.Add(new KeyValuePair<string, string>("1", "abc"));
list.Add(new KeyValuePair<string, string>("2", "def"));
list.Add(new KeyValuePair<string, string>("3", "ghi"));
How to select the value from this list.
Which means I need to pass 1 to the list and need to take the equal value "abc".How to do this? input is 1,output is abc.
It sounds like you just want:
var value = list.First(x => x.Key == input).Value;
That's if you're sure the key will be present. It's slightly trickier otherwise, partly because KeyValuePair is a struct. You'd probably want:
var pair = list.FirstOrDefault(x => x.Key == input);
if (pair.Key != null)
{
// Yes, we found it - use pair.Value
}
Any reason you're not just using a Dictionary<string, string> though? That's the more natural representation of a key/value pair collection:
var dictionary = new Dictionary<string, string>
{
{ "1", "abc" },
{ "2", "def" },
{ "3", "ghi" }
};
Then:
var value = dictionary[input];
Again, assuming you know the key will be present. Otherwise:
string value;
if (dictionary.TryGetValue(input, out value))
{
// Key was present, the value is now stored in the value variable
}
else
{
// Key was not present
}
Why are you not using a Dictionary? http://msdn.microsoft.com/en-us/library/xfhwa508.aspx
It seems to me this would solve your problem, and it's much easier to use.

Categories

Resources