Collections like HashTable and Dictionary don't allow to add a value with the same key but I want to store the same values with the same keys in a Collection<int,string>.
Is there a built-in collection which lets me do this?
You can use a List<T> containing a custom class, or even a List<Tuple<int,string>>.
List<Tuple<int,string>> values = new List<Tuple<int,string>>();
values.Add(Tuple.Create(23, "Foo"));
values.Add(Tuple.Create(23, "Bar"));
Alternatively, you can make a Dictionary<int, List<string>> (or some other collection of string), and populate the values in that way.
Dictionary<int, List<string>> dict = new Dictionary<int, List<string>>();
dict.Add(23, new List<string> { "Foo", "Bar" });
This has the advantage of still providing fast lookups by key, while allowing multiple values per key. However, it's a bit trickier to add values later. If using this, I'd encapsulate the adding of values in a method, ie:
void Add(int key, string value)
{
List<string> values;
if (!dict.TryGetValue(key, out values))
{
values = new List<string>();
dict[key] = values;
}
values.Add(value);
}
Use a List with a custom Class.
public class MyClass
{
public int MyInt { get; set; }
public string MyString { get; set; }
}
List<MyClass> myList = new List<MyClass>();
myList.Add(new MyClass { MyInt = 1, MyString = "string" });
In short: The easiest way to go would be a generic List<T> collection while skiping the ArrayList class. Because, there are some performance considerations that you need to take into account.
In addition, you can also use List<KeyValuePair<string,int>>.
This will store a list of KeyValuePair 's that can be duplicate.
In deciding whether to use the List<T> or ArrayList class, both of which have similar functionality, remember that the List<T> class performs better in most cases and is type safe. If a reference type is used for type T of the List<T> class, the behavior of the two classes is identical. However, if a value type is used for type T, you need to consider implementation and boxing issues.
As reference: you may use the following MSDN article - List Class.
Related
I have a Dictionary<string, List<string>> and would like to expose the member as read only. I see that I can return it as a IReadOnlyDictionary<string, List<string>>, but I can't figure out how to return it as an IReadOnlyDictionary<string, IReadOnlyList<string>>.
Is there a way to do this? In c++ I'd just be using const, but C# doesn't have that.
Note that simply using a IReadOnlyDictionary does not help in this case, because I want the values to be read only as well. It appears the only way to do this is build another IReadOnlyDictionary, and add IReadOnlyList to them.
Another option, which I wouldn't be thrilled with, would be to create wrapper which implements the interface IReadOnlyDictionary>, and have it hold a copy of the original instance, but that seems overkill.
It would be as easy as casting the whole dictionary reference to IReadOnlyDictionary<string, IReadOnlyList<string>> because Dictionary<TKey, TValue> implements IReadOnlyDictionary<TKey, TValue>.
BTW, you can't do that because you want the List<string> values as IReadOnlyList<string>.
So you need something like this:
var readOnlyDict = (IReadOnlyDictionary<string, IReadOnlyList<string>>)dict
.ToDictionary(pair => pair.Key, pair => pair.Value.AsReadOnly());
Immutable dictionaries
This is just a suggestion, but if you're looking for immutable dictionaries, add System.Collections.Immutable NuGet package to your solution and you'll be able to use them:
// ImmutableDictionary<string, ImmutableList<string>>
var immutableDict = dict
.ToImmutableDictionary(pair => pair.Key, pair => pair.Value.ToImmutableList());
Learn more about Immutable Collections here.
Given the fact that you're specifically looking for a read-only Dictionary<string, List<string>>, you're basically looking exactly for a Lookup.
The Dictionary object has a ToLookup() extension.
First, you'll have to create a new dictionary with the desired content types:
var dicWithReadOnlyList = dic.ToDictionary(
kv => kv.Key,
kv => kv.Value.AsReadOnly());
Then you can just return the new dictionary, since IReadOnlyDictionary is a supertype of Dictionary.
Why do you need to do that? Because Dictionary<T, A> is not a supertype of Dictionary<T, B>, even if A is a supertype of B. Why? Consider the following example:
var dic = new Dictionary<T, B>();
Dictionary<T, A> dic2 = dic; // Imagine this were possible...
dic2.Add(someT, someA); // ...then we'd have a type violation here, since
// dic2 = dic requires some B as the value.
In other words, TValue in Dictionary is not covariant. From an object-orientied point of view, covariance should be possible in the read-only version of the dictionary, but there are legacy issues in the .NET framework which prevent this (see the part starting with "UPDATE" in this question for details).
I run into the same problem. I solved it on the following way.
List<string> list = new List<string>();
Dictionary<string, IReadOnlyCollection<string>> dic = new Dictionary<string, IReadOnlyCollection<string>>();
IReadOnlyDictionary<string, IReadOnlyCollection<string>> dicRo = new ReadOnlyDictionary<string, IReadOnlyCollection<string>>(dic);
list.Add("Test1");
dic["T"] = list.AsReadOnly();
ist.Add("Test2");
This has the positiv effekt, that you
can still add items to the list
can still add items to the dictionary
can't edit the ReadOnlyDictionary
can't edit the ReadOnlyCollection
can't cast it into a Dictionary
can't cast it into a List
have your ReadOnlyDictionary always up to date
Maybe this will help someone.
If you want to return a read only dictionary but still be able to mutate the dictionary and list in your class you could use casting to get back the list type.
This example is a bit contrived, but shows how it could work.
public class MyClass
{
Dictionary<string, IReadOnlyList<string>> _dictionary;
public IReadOnlyDictionary<string, IReadOnlyList<string>> Dictionary { get { return _dictionary; } }
public MyClass()
{
_dictionary = new Dictionary<string, IReadOnlyList<string>>();
}
public void AddItem(string item)
{
IReadOnlyList<string> readOnlyList = null;
List<string> list = null;
if (!_dictionary.TryGetValue(item, out readOnlyList))
{
list = new List<string>();
_dictionary.Add(item, list);
}
else
list = readOnlyList as List<string>;
list.Add(item);
}
}
If you goal is to have the property be immutable, then using a ReadOnlyDictionary would be the best option.
https://msdn.microsoft.com/en-us/library/acdd6hb7.aspx
You can use this to expose the object as readonly.
You could also use properties get; set; and only allow the get to be public.
But Matias answer seems to be more fitting.
Suppose I have a class Composite that is constructed from a dictionary of instruments and weights.
public IReadOnlyDictionary<Instrument, double> Underlyings{ get; private set; }
public Composite(
Id id,
Currency currency,
Dictionary<Instrument, double> underlyings
)
{
Underlyings= underlyings;
}
}
This class is exposed to the client, and I want the client to be able to modify the existing keys' values within Underlyings, but not add new key-value pairs to Underlyings.
Then making Underlyings a ReadOnlyDictionary will not work as the client code will not be able to modify the values for existing keys. So my solution was to take the wrapper around a dictionary from this answer and modify the setter for TValue IDictionary<TKey, TValue>.this[TKey key] such that existing values can be modified. But this seems like a silly solution - is there an easier way than writing a wrapper class to have a dictionary which has modifiable existing key-value pairs, but cannot have new key-value pairs added to it? Apologies for the very simplistic question.
No, there is no standard dictionary that only allows updates. Its all or nothing.
As you have discovered, you have to create it your own, or find an implementation that is already there. Overriding the Add and this[] property is a solution that might work for you.
You can use ReadOnlyDictionary, but provide another method to modify value of given key. Something like:
Dictionary<KeyType, ValueType> _dictionary;
public ReadOnlyDictionary<KeyType, ValueType> Dictionary => new ReadOnlyDictionary<KeyType, ValueType>(_dictionary);
public void ChangeValue(KeyType key, ValueType value) => _dictionary[key].Value = value;
As you said, create a wrapper over a dictionary or inherit from the dictionary class an override Add.
Not a good way but a hack.
Generate a wrapper around your data and Use a ReadOnlyDictionary which is introduced in .NET 4.5.
class MyDataWrapper<T>
{
public T Data { set; get; }
}
var dicData = new Dictionary<int, MyDataWrapper<string>>();
dicData[0] = new MyDataWrapper<string> { Data = "0" };
dicData[1] = new MyDataWrapper<string> { Data = "0" };
var myDic = new ReadOnlyDictionary<int, MyDataWrapper<string>>(dic);
myDic[1].Data = "2";
// myDic[1] = new ... compile error
// myDic.Add() compile error
I need a Pair list, with "string", "string".
Tried :
Dictionary<string, string> Categories= new Dictionary<string, string>();
but can't add "700", "2" and "700", "3". I need a Pair where I can add everythings, when I want. Like a Vector that can contain N Vector (string, string). Which structure I need? Quickly, because I need to compaire them in LINQ, after :
myStructs = from MyObject s in MyObjects
join c in Categories on s.IDCategory.UniqueID equals c.Key
join d in Categories on s.Stars equals d.Value
select s;
Try List<Tuple<string, string>>, or for increased readability, simply make a new type.
If you need it to make sense during linq, you could transfer the tuple into an anonymous type (using let here) to give the type some sensible property names:
var items = new List<Tuple<string, string>>
{
new Tuple<string, string>("Adam", "1"),
new Tuple<string, string>("Adam", "2")
};
var names = from i in items
let person = new { Name = i.Item1, Number = i.Item2 }
select person.Name;
Makes it a little more readable during a linq query.
It the type is used a lot, I advise creating your own type with better property names for clarity as in Servy's answer. In the long run, Tuple<string, int, bool> is a lot less obvious than:
class Person
{
public string Name { get; set; }
public int Age { get; set; }
public bool LikesCake { get; set; }
}
Tuple equality is based on the equality of all it's properties against an instance of the same type of tuple. For example, new Tuple("Adam", "1").Equals(new Tuple("Adam", "1")) will be true.
Lists also do not stop duplicate items. If you need to enforce uniqueness across all the properties, then HashSet<Tuple<string, string>> is what you need.
Just create your own.
public class Pair
{
public string First {get;set;}
public string Second {get;set;}
}
Then you can have a List<Pair> to hold your data.
There are several possible library classes that you could re-purpose for your own needs, but in particular if this pair actually represents something (meaning you'd rename the class and the properties to something more meaningful) then it can be useful to have it in its own class to denote that. If you did want to just re-use an existing type then Tuple<string,string> would probably be the best choice.
Try using List<KeyValuePair<string, string>>.
A Dictionary is a hashed location keys, so you cannot have duplicates in the dictionary. You could have a list of type <string,string> either by using aKeyValuePair or Tuple
A List<KeyValuePair<string, string>> would probably work well if you're in .NET 3.5 or below, and if 4 or above, List<Tuple<string, string>> would be a winner.
This is similar to How to keep the order of elements in hashtable, except for .NET.
Is there any Hashtable or Dictionary in .NET that allows you to access it's .Index property for the entry in the order in which it was added to the collection?
A NameValueCollection can retrieve elements by index (but you cannot ask for the index of a specific key or element). So,
var coll = new NameValueCollection();
coll.Add("Z", "1");
coll.Add("A", "2");
Console.WriteLine("{0} = {1}", coll.GetKey(0), coll[0]); // prints "Z = 1"
However, it behaves oddly (compared to an IDictionary) when you add a key multiple times:
var coll = new NameValueCollection();
coll.Add("Z", "1");
coll.Add("A", "2");
coll.Add("Z", "3");
Console.WriteLine(coll[0]); // prints "1,3"
The behaviour is well documented, however.
Caution: NameValueCollection does not implement IDictionary.
As an aside: Dictionary<K,V> does not have any index you can use, but as long as you only add elements, and never remove any, the order of the elements is the insertion order. Note that this is a detail of Microsoft's current implementation: the documentation explicitly states that the order is random, so this behavior can change in future versions of the .NET Framework or Mono.
If this is something that you need to keep track of efficiently, then you are using the wrong data structure. Instead, you should use a SortedDictionary where the key is tagged with the index of when it was added (or a timestamp) and a custom IComparer that compares two keys based on the index (or the timestamp).
You can use a separate list to store the elements in the order they are added. Something along the lines of the following sample:
public class ListedDictionary<TKey, TValue> : IDictionary<TKey, TValue>
{
List<TValue> _list = new List<TValue>();
Dictionary<TKey, TValue> _dictionary = new Dictionary<TKey,TValue>();
public IEnumerable<TValue> ListedValues
{
get { return _list; }
}
public void Add(TKey key, TValue value)
{
_dictionary.Add(key, value);
_list.Add(value);
}
public bool ContainsKey(TKey key)
{
return _dictionary.ContainsKey(key);
}
public ICollection<TKey> Keys { get { return _dictionary.Keys; } }
public bool Remove(TKey key)
{
_list.Remove(_dictionary[key]);
return _dictionary.Remove(key);
}
// further interface methods...
}
Is there any Hashtable or Dictionary in .NET that allows you to access it's .Index property for the entry in the order in which it was added to the collection?
No. You can enumerate over all the items in a Hastable or Dictionary, but these are not guaranteed to be in any sort of order (most likely they are not)
You would have to either use a different data structure altogether, (such as SortedDictionary or SortedList) or use a separate list to store the order in which they were added. You would want to wrap the ordered list and your dictionary/hashtable in another class to keep them synched.
Take a look at the OrderedDictionary class. Not only can you access it via keys, but also via an index (position).
An alternative is to create an array of stuctures, so instead of using
dictionary.Add{"key1","value1"}
you create a structure with the key/value like:
public struct myStruct{
private string _sKey;
public string sKey{
get { return _sKey; }
set { _sKey = value; }
}
private string _sValue;
public string sValue {
get { return _sValue; }
set { _sValue = value; }
}
}
// create list here
List<myStruct> myList = new List<myStruct>();
// create an instance of the structure to add to the list
myStruct item = new myStruct();
item.sKey = "key1";
item.sValue = "value1";
// then add the structure to the list
myList.Add(item);
Using this method you can add extra dimensions to the list without too much effort, just add a new member in the struct.
Note, if you need to modify items in the list after they have been added you will have to change the struct into a class. See this page for more info on this issue: error changing value of structure in a list
I need some sort of way to store key/value pairs where the value can be of different types.
So I like to do:
int i = 12;
string s = "test";
double x = 24.1;
Storage.Add("age", i);
Storage.Add("name", s);
Storage.Add("bmi", x);
And later retrieve the values with:
int a = Storage.Get("age");
string b = Storage.Get("name");
double c = Storage.Get("bmi");
How should a Storage like this look like?
Thanks,
Erik
Well, you could use Dictionary<string, dynamic> in C# 4 / .NET 4 - but other than that, you can't do it with exactly the code shown because there's no type which is implicitly convertible to int, string and double. (You could write your own one, but you'd have to list each type separately.)
You could use Dictionary<string, object> but then you'd need to cast the results:
int a = (int) Storage.Get("age");
string b = (string) Storage.Get("name");
double c = (double) Storage.Get("bmi");
Alternatively, you could make the Get method generic:
int a = Storage.Get<int>("age");
// etc
You could declare a Dictionary containing just the type object and then cast your results; .e.g.
Dictionary<string, object> storage = new Dictionary<string,object>();
storage.Add("age", 12);
storage.Add("name", "test");
storage.Add("bmi", 24.1);
int a = (int)storage["age"];
string b = (string)storage["name"];
double c = (double)storage["bmi"];
However, this isn't that elegant. If you know you are always going to be storing age, name, bmi I would create an object to encapsulate those and store that instead. E.g.
public class PersonInfo
{
public int Age { get; set; }
public string Name { get; set; }
public double Bmi { get; set; }
}
And then use that insead of the Dictionary... e.g.
PersonInfo person1 = new PersonInfo { Name = "test", Age = 32, Bmi = 25.01 };
int age = person1.Age;
etc.
Why not use:
Dictionary<string, object>
You can create an extension method to cast them when you get them:
public static class DictionaryExcetions
{
public static T Get<T>(this Dictionary<string, object> instance, string name)
{
return (T)instance[name];
}
}
var age = dictionary.Get<int>("age");
Given that you don't want a strongly typed data collection then I would have thought a HashTable would be suitable for your situation. You could create an Extention method for this also, like another poster suggested for the Dictionary implementation.
E.g.
public static class StorageExtentions
{
public static T Get<T>(this Hashtable table, object key)
{
return (T) table[key];
}
}
Your code would then look like:
int i = 12;
string s = "test";
double x = 24.1;
Hashtable Storage = new Hashtable();
Storage.Add("age", i);
Storage.Add("name", s);
Storage.Add("bmi", x);
int a = Storage.Get<int>("age");
string b = Storage.Get<string>("name");
double c = Storage.Get<double>("bmi");
maybe it is an old question, but I am addressing the guys who come here to find the answer
if the value is not a fixed type one of the choices is using Hashtable
please look at the implementation of both Dictionary and Hashtable
public class Dictionary<TKey, TValue> : ICollection<KeyValuePair<TKey, TValue>>, IEnumerable<KeyValuePair<TKey, TValue>>, IEnumerable, IDictionary<TKey, TValue>, IReadOnlyCollection<KeyValuePair<TKey, TValue>>, IReadOnlyDictionary<TKey, TValue>, ICollection, IDictionary, IDeserializationCallback, ISerializable
{
...
}
public class Hashtable : ICollection, IEnumerable, IDictionary, ISerializable, IDeserializationCallback, ICloneable
{
...
}
as it gets more clear from above code snippets, both implement literally the same interfaces but in Hashtable there is no type on both key & value since both of them considered to be intrinsically objects, for example you can see from add method in Hashtable:
public virtual void Add(object key, object value);
so for the cases of not having fixed keys and/or values, I recommend using Hashtable, therefore you don't need to add extra extension methods or override default behavior of a dictionary any more.
Dictionary<string, object>
You can use a Dictionary<string,object> and then you can put anything you want into it. You would have to cast the results to the right type when you get them out though.
Looking at your example though you might want to consider whether a simple class to store the data might be more what you want and allow better type safety. It depends on whether you have a limited set of things to put in the class or if you do need the potentially unlimited/unknown storage of a dictionary.
Dictionary is clearly the quickest solution.
Another way could be to store a custom class in which you could store the actual value and the information regarding its type