In my console application I have one hundred county codes and their names. For example:
"01" : "Floyd"
"02" : "Wabash"
When my program uses the values, it reads "01","02"...and I want to get "Floyd", etc...
This list won't grow in future, I am just hard coding them, How do you suggest to access these?
Maybe in a static class? Maybe in a JSON format? Other ways?
Dictionary is what you look for: MSDN link
Short example:
void Main()
{
var dic = new Dictionary<int,string>();
// Instead of having a method to check, we use this Action
Action<int> tryDic = (i) => {
if (dic.ContainsKey(i))
Console.WriteLine("{0}:{1}", i, dic[i]);
else
Console.WriteLine("dic has no key {0}", i);
};
dic.Add(1,"one");
dic.Add(2,"two");
// dic.Keys = 1, 2
// dic.Values = one, two
tryDic(1); // one
tryDic(3); // dic has no key 3 (Happens in Action above)
dic[1]="wow";
tryDic(1); // wow
}
Just use a simple Dictionary<string, string>; if you really want you can wrap it in a class to add some behavior such as handling keys not found, or already existing
You are looking for a Dictionary<string, string>
var values = new Dictionary<string,string>();
values.Add("01", "Floyd");
...
var value = values["01"]; // Floyd
Related
I've been looking for answers but for some reasons all I found doesn't match with my use.
I'm not very familiar to c#, I have a dictionary
public Dictionary<int, int> deck = new Dictionary<int, int>();
I want to take ten first values of this dictionary and put it in an array like
public string[] cardP1 = new string[10];
, I tried some things with .Take or .CopyTo, I also played with the Values but it is still not working.
you can use LINQ very easily like this :
var q = (from p in deck.Keys select p).Take(10).ToArray();
if you want Values you can just change the deck.keys to deck.values
it will give you the 10 first keys.
EDIT Or as Jakub Dąbek commented :
var items = deck.Keys.Take(10).ToArray();
Check this:
if(deck.Count>=10)
{
cardP1 = deck.Take(10).Select(x => x.Value.ToString()).ToArray();
}
Or if you want to have some custom string for example: Card 1: 4
you can go with:
cardP1 = deck.Take(10).Select(x => string.Format("Card {0}: {1}", x.Key, x.Value) ).ToArray();
My data source could have duplicate keys with values.
typeA : 1
typeB : 2
typeA : 11
I chose to use NameValueCollection as it enables entering duplicate keys.
I want to remove specific key\value pair from the collection, but NameValueCollection.Remove(key) removes all values associated with the specified key.
Is there a way to remove single key\value pair from a NameValueCollection,
OR
Is there a better collection in C# that fits my data
[EDIT 1]
First, thanks for all the answers :)
I think I should have mentioned that my data source is XML.
I used System.Xml.Linq.XDocument to query for type and also it was handy to remove a particular value.
Now, my question is, for large size data, is using XDocument a good choice considering the performance?
If not what are other alternatives (maybe back to NameValueCollection and using one of the techniques mentioned to remove data)
The idea of storing multiple values with the same key is somehow strange. But I think you can retrieve all values using GetValues then remove the one you don't need and put them back using Set and then subsequent Add methods. You can make a separate extension method method for this.
NameValueCollection doesn't really allow to have multiple entries with the same key. It merely concatenates the new values of existing keys into a comma separated list of values (see NameValueCollection.Add.
So there really is just a single value per key. You could conceivably get the value split them on ',' and remove the offending value.
Edit: #ElDog is correct, there is a GetValues method which does this for you so no need to split.
A better option I think would be to use Dictionary<string, IList<int>> or Dictionary<string, ISet<int>> to store the values as discrete erm, values
You may convert it to Hashtable
var x = new NameValueCollection();
x.Add("a", "1");
x.Add("b", "2");
x.Add("a", "1");
var y = x.AllKeys.ToDictionary(k => k, k=>x[k]);
make your own method, it works for me --
public static void Remove<TKey,TValue>(
this List<KeyValuePair<TKey,TValue>> list,
TKey key,
TValue value) {
return list.Remove(new KeyValuePair<TKey,TValue>(key,value));
}
then call it on list as --
list.Remove(key,value); //Pass the key value...
Perhaps not the best way, but....
public class SingleType
{
public string Name;
public int Value;
}
List<SingleType> typeList = new List<SingleType>();
typeList.Add (new SingleType { Name = "TypeA", Value = 1 });
typeList.Add (new SingleType { Name = "TypeA", Value = 3 });
typeList.Remove (typeList.Where (t => t.Name == "TypeA" && t.Value == 1).Single());
You can use the Dictionary collection instead:
Dictionary<string, int> dictionary = new Dictionary<string, int>();
dictionary.Add("typeA", 1);
dictionary.Add("typeB", 1);
When you try to insert type: 11 it will throw exception as Key already exists. So you can enter a new key to insert this data.
Refer this Tutorial for further help.
This may seem an odd thing to want to do but ignoring that, is there a nice concise way of converting a List<string> to Dictionary<string, string> where each Key Value Pair in the Dictionary is just each string in the List. i.e.
List = string1, string2, string3
Dictionary = string1/string1, string2/string2, string3/string3
I have done plenty of searching and there are literally dozens of examples on Stackoverflow alone of doing it in the opposite direction but not this way round.
The reason for doing this is I have two third part components and changing them is out of my hands. One returns a list of email addresses as a List<string> and the other send emails where the To parameter is a Dictionary<string, string>. The key of the dictionary is the email address and the value is their real name. However, I don't know the real name but it still works if you set the real name to the email address as well. Therefore why I want to convert a List to a Dictionary<string, string>. There are plenty of ways of doing this. A foreach loop on the list which adds a kvp to a dictionary. But I like terse code and wondered if there was a single line solution.
Try this:
var res = list.ToDictionary(x => x, x => x);
The first lambda lets you pick the key, the second one picks the value.
You can play with it and make values differ from the keys, like this:
var res = list.ToDictionary(x => x, x => string.Format("Val: {0}", x));
If your list contains duplicates, add Distinct() like this:
var res = list.Distinct().ToDictionary(x => x, x => x);
EDIT To comment on the valid reason, I think the only reason that could be valid for conversions like this is that at some point the keys and the values in the resultant dictionary are going to diverge. For example, you would do an initial conversion, and then replace some of the values with something else. If the keys and the values are always going to be the same, HashSet<String> would provide a much better fit for your situation:
var res = new HashSet<string>(list);
if (res.Contains("string1")) ...
Use this:
var dict = list.ToDictionary(x => x);
See MSDN for more info.
As Pranay points out in the comments, this will fail if an item exists in the list multiple times.
Depending on your specific requirements, you can either use var dict = list.Distinct().ToDictionary(x => x); to get a dictionary of distinct items or you can use ToLookup instead:
var dict = list.ToLookup(x => x);
This will return an ILookup<string, string> which is essentially the same as IDictionary<string, IEnumerable<string>>, so you will have a list of distinct keys with each string instance under it.
EDIT
another way to deal with duplicate is you can do like this
var dic = slist.Select((element, index)=> new{element,index} )
.ToDictionary(ele=>ele.index.ToString(), ele=>ele.element);
or
easy way to do is
var res = list.ToDictionary(str => str, str=> str);
but make sure that there is no string is repeating...again otherewise above code will not work for you
if there is string is repeating than its better to do like this
Dictionary<string,string> dic= new Dictionary<string,string> ();
foreach(string s in Stringlist)
{
if(!dic.ContainsKey(s))
{
// dic.Add( value to dictionary
}
}
By using ToDictionary:
var dictionary = list.ToDictionary(s => s);
If it is possible that any string could be repeated, either do a Distinct call first on the list (to remove duplicates), or use ToLookup which allows for multiple values per key.
You can use:
var dictionary = myList.ToDictionary(x => x);
I am drawing a blank here.. I am using MVC and my model doesn’t have the Value Name, it just has the ID.
The problem is with ‘itm.DegreeTypeId’ it is just an int. But I need to match it up with a string name.. so DegreeTypeId 1 = Associates Degree, 2 = Bachelor, 3 = MBA etc.
I don’t want to update the model to have the name, but instead to a quick lookup. What’s the best way to proceed here? I know I can create a method and have it return the string based on a number but there has to be a better cleaner way.
string education = string.Empty;
int eduCount = 0;
foreach (var itm in candidate.Educations)
{
if (eduCount > 0) education += "<br><br>";
education += string.Format("<b>{0}</b><br>{1} {2}<br>{3}Graduated: {4}<br>",
itm.DegreeTypeId,
itm.InstitutionName,
itm.InstitutionLocation,
itm.GraduatedOn.HasValue
? string.Format("{0:MMMM yyyy}", itm.GraduatedOn.Value)
: string.Empty);
eduCount++;
}
Try using a Dictionary
static readonly Dictionary<int, string> Degrees = new Dictionary<int, string>() {
{1, "Associates Degree"},
{2, "Bachelor"},
{3, "MBA"},
...
};
So the relevant snippet looks like this:
education += string.Format("<b>{0}</b><br>{1} {2}<br>{3}Graduated: {4}<br>",
Degrees(itm.DegreeTypeId),
...
It's not entirely clear what you're after, but a Dictionary<int, string> could work (or the reverse if you're trying to look things up the other way). Even a string[] could be a simple solution for int to string conversion:
static readonly string[] DegreeTypeNames = { null, // Unused
"Associates Degree",
"Bachelor",
"MBA"
};
That's useful (and performs really well) if you've got a lot of consecutive values, but if they're not all consecutive, the dictionary approach would be better.
If you need to refer to these IDs in code, you should potentially consider using an enum.
I am getting a datatable with customer data from a MySql databaes and a customer object from a web service.
I want to compare every value in the datatable with the values in the object and if there is one field that differs I want to perfrom some tasks.
I know I can get the values from the datatable with:
string mCompanyName = row["Company Name"].ToString();
string mCreatedDate = row["Created Date"].Tostring();
//etc..
Then I get the values from the web service
string wsCompanyName = customer.companyName;
string wsCreatedDate = customer.createdDate;
There are about 50 fields and doing
if( mCompanyName != wsCompanyName & mCreatedDate != wsCreatedDate and so on..) (or similar)
{
//Do something
}
seems to be a bit tedious and not very nice so how should I perform this? Is there a much better way to chuck it into a list and use some fancy LINQ?
Thanks in advance.
For cases like this I sometimes put them ("the objects") in something IEnumerable (make sure to "line them up") and use the SequenceEqual extension method. It performs standard Equals()'ity and is "cheap enough for my usage".
For instance:
var equal = (new object[] { row["A"], row["B"] })
.SequenceEqual(new object[] { x.A, x.B });
This requires LINQ, of course.
I'd put them in a Dictionary and search that way:
Dictionary<string, string> mData = new Dictionary<string, string>();
mData.Add("Company Name", row["Company Name"].ToString());
Dictionary<string, string> wsData = new Dictionary<string, string>();
wsData.Add("Company Name", customer.CompanyName);
Then loop through:
foreach (KeyValuePair<string, string> pair in mData)
{
if (wsData[pair.Key] == pair.Value)
{
// Do something
}
}
This way, for every entry in mData (the data from your database), it will look for an entry in wsData with the same name.
I wouldn't create individual variables for each piece of data. It would be difficult to maintain, and would not scale well (lots of copy and pastes).
I think this might help you, but it needs to modify this to use in your scenerio stackoverflow link