C# Comparison between Dictionary<string, int> and int result [duplicate] - c#

This question already has answers here:
Get dictionary key by value
(11 answers)
Closed 2 years ago.
This is my function where I created a dictionary:
public int Scale(string value)
{
//some calculs
int result = 19; // or int between 0 and 40
this.stringToInt = new Dictionary<string, int>()
{
{"1p",00},{"2p",01},{"3p",03} ... {"300p",40}
};
// Here I try to do something like that: if(result == (int in dictionary) return associate string
}
I tried the below code:
if (this.stringToInt.ContainsValue(result)
{
return this.stringToInt[result]; // I don't know what to write between hook (result doesn't work).
}
I don't know how to return associate string.
Thank you in advance for help!

var keyValuePair = this.stringToInt.FirstOrDefault(x => x.Value == result);
if (!keyValuePair.Equals(new KeyValuePair<string, int>()))
{
// found, use keyValuePair.Key
}
This would work i guess using Linq. But only returns the first found value. If the value is more than once in the dictionary, only the first one found is returned.
But you should do it like in the comment from #nanu_nana

Related

Checking multiple values of a dictionary to verify an answer

I managed to create an input field that is able to be checked and verified upon a question via creating another text field and linking that to said question, so for example if the value of the question was '1', the answer would be '1'. Then I made a text comparison, so that if what the user wrote = that text field the answer would be correct.
However, I realise that sometimes someone can write something else. For example in the question ' What do you think about tigers', there isn't just one possible answer. And therefore, the way I did that for the input field does not exactly work (does it?).
I did quite a lot of research and found out about dictionaries, but since they only have one key value that wouldn't help, and then I found out about lists, which might?
So my question is whether it is possible, and how, to create a list that's integer values is somehow linked to the values of the overarching question, so that if the random value is 1, the list value is 1 as well, and then check if what is written matches any of the answers with that random value.
If what I just said didn't make sense, here's an example:
Current behavior:
SURVEY: Do you like cats?
INPUT FIELD: Yes I do
HIDDEN TEXT FIELD : Yes I do
input field = hidden text field and therefore correct
Ideal behavior:
SURVEY: Do you like cats?
INPUT FIELD: I do like cats
POSSIBLE ANSWERS: I do like cats, Yes I do etc.
INPUT FIELD contains an answer in the list which matches the question and therefore correct.
I thought you could use the .Contains function, but I didn't know how to link it all together.
EDIT:
I tried to solve this problem via the creation of a dictionary and searching for a key (which I believe was the right way to do this), but for some reason this code doesn't even work when checking it? (it's like the .containsKey function doesn't work?)
public string questions = "hi;weird;by";
Dictionary<int, string> tester = new Dictionary<int, string>();
// Use this for initialization
void Start ()
{
tester.Add(1, questions);
tester.Add(2, "hello");
tester.Add(3, "by");
tester.Add(4, "hi");
tester.Add(5, "bye");
}
// Update is called once per frame
void Update ()
{
}
public void hello ()
{
if(tester.ContainsKey(2))
{
string value = tester[2];
Debug.Log("Correct");
}
}
EDIT 1:
Following what trashr0X said I tried doing it by having a dictionary script in the main camera and a script in the inputfield, but for some reason when I load it nothing works on the console:
LIST
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using System.Linq;
public class Listpractice : MonoBehaviour
{
Dictionary<int, List<string>> tester = new Dictionary<int, List<string>>();
List<string> possibleAnswersToQuestionZero = new List<string>();
// Use this for initialization
void Start () {
possibleAnswersToQuestionZero.Add("Hello");
possibleAnswersToQuestionZero.Add("By");
tester.Add(0, possibleAnswersToQuestionZero);
}
// Update is called once per frame
void Update ()
{
}
public void hello ()
{
var toCheck = tester[0].FirstOrDefault(x => x == GameController.hello);
if (toCheck != null)
{
Debug.Log("Hi!");
}
}
}
INPUT FIELD
public class QAClass07
{
public string Answer = "";
public string Question = "";
QAClass07 result = new QAClass07();
}
public static string hello;
void Start()
{
GameObject a = gameObject;
hello = a.transform.Find("Text").GetComponent<Text>().text;
}
// registers what the user writes
public void getInput(string guess)
{
// Does something assuming someone enters something
if (GetComponent<InputField>() != null)
{
hello = GetComponentInChildren<Text>().text;
}
}
Simply use Dictionary<int, List<string>> and then add all the answers to the corresponding question id.
var questions = new List<string> { "hi", "weird", "by" };
var tester = new Dictionary<int, List<string>>();
// Use this for initialization
void Start ()
{
tester.Add(1, questions);
tester.Add(2, new List<string> { "hello" });
tester.Add(3, new List<string> { "by" });
tester.Add(4, new List<string> { "hi" });
tester.Add(5, new List<string> { "bye" });
}
public void hello ()
{
if(tester.ContainsKey(2))
{
var answers = tester[2] ?? new List<string>();
// now you have all answers linked to question with id 2 in answers variable
}
}
"I did quite a lot of research and found out about dictionaries, but since they only have one key value that wouldn't help, and then I found out about lists, which might?"
Yes, a Dictionary<TKey, TValue> does comprise of key-value pairs of a particular type each; you can declare the type of it's key to be int (corresponding to the index of the question currently asked), and declare the type of it's value to be List<string>, to hold possible answers for that question.
// key is question index, value is a list of possible answers for that question
var dictionary = new Dictionary<int, List<string>>();
// list of possible answers for question 0 (random question number chosen for the example)
var possibleAnswersToQuestionZero = new List<string>();
possibleAnswersToQuestionZero.Add("Possible Answer to question 0");
possibleAnswersToQuestionZero.Add("Another possible answer to question 0");
// add that list to the dictionary at key 0.
// you should be also checking if the key exists before trying to access it's value,
// and what happens if the list returned for that key is null or empty.
dictionary.Add(0, possibleAnswersToQuestionZero);
To check if the answer submitted by the user (let's assume it is saved in a variable named userInput) for question 0 is in the list of possible answers for that key, we would do:
// check if the list at dictionary[0] has at least one instance of userInput,
// otherwise return null
var toCheck = dictionary[0].FirstOrDefault(x => x == userInput);
// if the result is not null, the answer was found
if (toCheck != null)
{
// answer found
}

Getting a specific key from within a hashtable

So I have this Hashtable
Hashtable Months = new Hashtable();
Months.Add(0, "JANUARY");
Months.Add(1, "FEBRUARY");
Months.Add(2, "MARCH");
Months.Add(3, "APRIL");
Months.Add(4, "MAY");
Months.Add(5, "JUNE");
Months.Add(6, "JULY");
Months.Add(7, "AUGUST");
Months.Add(8, "SEPTEMBER");
Months.Add(9, "OCTOBER");
Months.Add(10, "NOVEMBER");
Months.Add(11, "DECEMBER");
I would like for the user to enter a month e.g."May" the be able to retrieve index[4] from an array within my program.
string Month = Console.ReadLine();
Basically to retrieve the index from the number of the corresponding Month entered.
Try this
var key = Months.Keys.Cast<int>().FirstOrDefault(v => Months[v] == "MAY");
Note: Don't forget to include this namespace - using System.Linq;
Get elements from your Hashtable in DictionaryEntry format
foreach (DictionaryEntry e in Months)
{
if ((string)e.Value == "MAY")
{
//get the "index" with e.Key
}
}
You can perform it just using a loop;
public List<string> FindKeys(string value, Hashtable hashTable)
{
var keyList = new List<string>();
IDictionaryEnumerator e = hashTable.GetEnumerator();
while (e.MoveNext())
{
if (e.Value.ToString().Equals(value))
{
keyList.Add(e.Key.ToString());
}
}
return keyList;
}
Usage;
var items = FindKeys("MAY",Months);
If you want to lookup the index from the month's name, a Dictionary<string, int> would be more suitable. The reason why I've swapped the parameters is becuase if you only want to lookup the index, and not also the other way around, this will be much faster.
You should declare the dictionary as case-insensitive so that it detects for instance may, May, mAy and MAY as the same thing:
Dictionary<string, int> Months = new Dictionary<string, int>(StringComparison.OrdinalIgnoreCase);
Then just use its TryGetValue() method whenever you want to get the month index:
int MonthIndex = 0;
if(Months.TryGetValue(Month, out MonthIndex)) {
//Month was correct, continue your code...
else {
Console.WriteLine("Invalid month!");
}

Cumulatively add values to Dictionary

I am trying to add values to a dictionary as they get determined based on certain conditions. The app has to loop through each line and once a certain condition has been met then a value must be added to the dictionary. Here is the code that is task with looping through the lines and determine values to be added.
foreach (var line in this.FileLines)
{
count++;
string[] bits = line.Split(',');
fineNumber = bits[0].Trim();
int length = bits.Length;
if (length == 9)
{
//other processing gets done here, code not included as its of no interest for this question
}
else
{
//AddErrorFinesToFile(line, fineNumber);
AddFinesToDictonary(fineNumber, line);
continue;
}
}
Then below is the actual method signature and its code, in this method I am simply trying to add values to the dictionary as they come.
public Dictionary<string, string> AddFinesToDictonary(string fineNumber, string errorLine)
{
Dictionary<string, string> erroredLines = new Dictionary<string, string>();
erroredLines.Add(fineNumber, errorLine);
return erroredLines;
}
The only problem that seems to arise here is, only the latest value gets added to the dictionary, meaning the previous added value gets overwritten.
Make erroredLines as global scope.
Dictionary<string, string> erroredLines = new Dictionary<string, string>();
foreach (var line in this.FileLines)
{
count++;
string[] bits = line.Split(',');
fineNumber = bits[0].Trim();
int length = bits.Length;
if (length == 9)
{
//other processing gets done here, code not included as its of no interest for this question
}
else
{
//AddErrorFinesToFile(line, fineNumber);
AddFinesToDictonary(fineNumber, line);
continue;
}
}
public void AddFinesToDictonary(string fineNumber, string errorLine)
{
erroredLines.Add(fineNumber, errorLine);
// return erroredLines;
}
And also no need to return erroredLines dictionary.
What about this;
Dictionary<string, string> erroredLines = new Dictionary<string, string>();
foreach (var line in this.FileLines)
{
count++;
string[] bits = line.Split(',');
fineNumber = bits[0].Trim();
int length = bits.Length;
if (length == 9)
{
//other processing gets done here, code not included as its of no interest for this question
}
else
{
erroredLines.Add(fineNumber, line);
continue;
}
}
after foreach you can use erroredLines dictionary.
The reason is every time you add data to the Directory you create a new one instead of adding data to the exists one
There are two choices you could make:
make a Dictionary out of the function
pass the Dictionary as an out ref to the function
#Hameed Syed 's answer has already given the first one (option 1).
Here is how you could pass the Dictionary as a ref parameter (out) to the function (option 2):
public void AddFinesToDictonary(out Dictionary<string,string>dict, string fineNumber, string errorLine)
{
dict.Add(fineNumber, errorLine);
}

Check if an item exist in the dictionary and remove it from the dictionary in C# [duplicate]

This question already has answers here:
Remove Item in Dictionary based on Value
(6 answers)
Closed 9 years ago.
The question should be clear from the title itself. I need to check if an item exist in the dictionary and remove it from the dictionary in C#. The only catch is that i have to do this using only the value item and not the key.
The declaration is as below:
IDictionary<string, myCustomClassObject> clients = new IDictionary<string, myCustomClassObject>();
Now i fill in the dictionary by:
clients["key"] = myCustomClassObject1;
Now how can i find and remove this item myCustomClassObject1 from my Dictionary. I only want to use the value item and not the key
Is this doabale...if so please guide...
regards
Edit: Thank you all....got valuable comments...probably have some thinking to do ...thanks
It depends on how you need it to perform. If you can accept O(N) performance, you could just do something like:
foreach(var pair in clients) {
if(pair.Value == expected) {
clients.Remove(pair.Key);
break;
}
}
However, if you need faster you would need two dictionaries - one the reverse of the other (i.e. keyed by the instances). So when adding, you would do:
clientsByKey.Add(key, value);
clientsByValue.Add(value, key);
so you can do (to remove-by-value):
string key;
if(clientsByValue.TryGetValue(value, out key)) {
clientsByValue.Remove(value);
clientsByKey.Remove(key);
}
or similarly (to remove-by-key):
Foo value;
if(clientsByKey.TryGetValue(key, out value)) {
clientsByValue.Remove(value);
clientsByKey.Remove(key);
}
It's not very efficient to search a dictionary by it's values. However, you can use Linq to find all entries with a given value.
IEnumerable<KeyValuePair<string, myCustomClassObject>> pairs = clients
.Where(entry => entry.Value.Equals(myCustomClassObject1)).ToList();
foreach (KeyValuePair<string, myCustomClassObject> kv in pairs)
clients.Remove(kv.Key);
This should do it. It removes all clients having a given value.
while (clients.ContainsValue(myCustomClassObject1))
clients.Remove(clients.Where(x => x.Value == myCustomClassObject1).FirstOrDefault().Key);
Or create a new dictionary without the values you want removed
clients = clients.Where(x => x.Value != myCustomClassObject1).ToDictionary(k => k.Key, v => v.Value);
If the collection only contains one item with the value to be removed then you can use one of the other answers here, which will work just fine.
However, if your collection can have multiple items with the same value then you need to be careful.
You cannot modify a collection while iterating over it, so you will need to find the keys of all the items that you want to remove in one loop and put them in a list, and then iterate over that list in a separate loop to delete the items.
For example:
using System;
using System.Collections.Generic;
using System.Linq;
namespace Demo
{
class Program
{
void run()
{
var dict = new Dictionary<string, int>
{
{"Key1", 1},
{"Key2", 2},
{"Key3", 3},
{"Key4", 2},
{"Key5", 4}
};
int valueToRemove = 2;
var keysToRemove = (from element in dict
where element.Value == valueToRemove
select element.Key).ToList();
foreach (var key in keysToRemove)
dict.Remove(key);
foreach (var element in dict)
Console.WriteLine("Key = {0}, Value = {1}", element.Key, element.Value);
}
static void Main(string[] args)
{
new Program().run();
}
}
}
Use,
Following will remove only first matching value
client newClient = new client();
foreach(KeyValuePair<string, client> client in clients) {
if(client.value.equals(newClient)) {
clients.remove(client.key);
break;
}
}
Or if you want to remove all matching values,
foreach(var client in clients.Where(kvp => kvp.Value == newClient).ToList()) {
clients.Remove(client.Key);
}

How to get string list of Enum descriptions? [duplicate]

This question already has answers here:
Enum ToString with user friendly strings
(25 answers)
Closed 4 years ago.
How can I get a List of an Enum's values?
For example, I have the following:
public enum ContactSubjects
{
[Description("General Question")]
General,
[Description("Availability/Reservation")]
Reservation,
[Description("Other Issue")]
Other
}
What I need to be able to do is pass ContactSubject.General as an argument and it returns the List of the descriptions.
This method needs to work with any Enum, not just ContactSubject (in my example). The signature should be something like GetEnumDescriptions(Enum value).
Something like that may work:
private static IEnumerable<string> GetDescriptions(Type type)
{
var descs = new List<string>();
var names = Enum.GetNames(type);
foreach (var name in names)
{
var field = type.GetField(name);
var fds = field.GetCustomAttributes(typeof(DescriptionAttribute), true);
foreach (DescriptionAttribute fd in fds)
{
descs.Add(fd.Description);
}
}
return descs;
}
however you may review some logic there: such as is it ok to start of names? how are you going to handle multiple Description attributes? What if some of them are missing - do you want a name or just skip it like above? etc.
just reviewed your question. For the VALUE you would have something like that:
private static IEnumerable<string> GetDescriptions(Enum value)
{
var descs = new List<string>();
var type = value.GetType();
var name = Enum.GetName(type, value);
var field = type.GetField(name);
var fds = field.GetCustomAttributes(typeof(DescriptionAttribute), true);
foreach (DescriptionAttribute fd in fds)
{
descs.Add(fd.Description);
}
return descs;
}
however it is not possible to place two Description attributes on single field, so I guess it may return just string.

Categories