Where to store two values for further comparing? - c#

After click over row in DataGridView I take value of two cells in this row:
string id = Convert.ToString(dataGridView1.Rows[e.RowIndex].Cells["Number"].Value);
string type = Convert.ToString(dataGridView1.Rows[e.RowIndex].Cells["dataGridViewTextBoxColumn46"].Value);
So, in which structure to store these values, that to take off them further?
In result I need to compare if id, type are exist in structure.
I tried Dictionary<int, int>. But it is hard to check if there values are in Dictionary like this: Dictionary<'id', 'type'>

A simple HashSet<Tuple<string, string>> would probably do:
HashSet<T> is a set of values which provides O(1) average lookup time for "contains" queries.
Tuple<T1, T2> is a class representing a pair of values, which uses value-type equality semantics, i.e. implements Equals and GetHashCode using the values stored inside the class, meaning that two different instances with same members will be considered equal (and this is important if you want to use them as HashSet<T> keys.
So, you would simply do something like:
// somewhere in your method or class
HashSet<Tuple<string, string>> hashset = new HashSet<Tuple<string, string>>();
// once you get the (id, type) pair:
hashset.Add(Tuple.Create(id, key));
// to check if the items are in the hashset:
if (hashset.Contains(Tuple.Create("a", "b"))
{
// do stuff
}
// to remove the item from the hashset
hashset.Remove(Tuple.Create("a", "b"));

Related

how to use more than one generic in a function in C#

I want to use more than one generic for a function but this doesn't work
protected async Task<Tlist,T> Send<Tlist,T>(string url,HttpMethod method,DateTimeSyncedAt ) where Tlist,T:class
{
}
Task won't support giving back multiple types as return value.
So you can use it as basically like
Task<T>
//The following wont work
Task<T,T1>
But you can do with using tuples or anything that is value pair
** Value Pairs **
Tuples:
A tuple is a data structure that has a specific number and sequence of values. The Tuple<T1,T2> class represents a 2-tuple, or pair, which is a tuple
Tuples are usually used by their operator
(T, T1)
Types in tuples could be more than two this depends on the use case.
Dictionaries:
Dictionary in C# is the generic collection type in the System.Collection.Generics namespace that contains Keys and Values.
Dictornary could be initialized by:
new Dictionary<string, string>(new []{new KeyValuePair<string, string>("SOMETHING1","SOMETHING2")});
If you wrap this dictionary to a variable our case called dictionary you can access the keys and the values separately by the following
dictionary.Keys // this is an array of keys in the dictionary
dictionary.Values // this is an array of values in the dictionary
Do this as the following:
protected async Task<(TList, T)> Send<TList,T>(string aParam,string bParam, string cParam) where TList : IEnumerable<T> where T : struct
{
}
This will return a tuple with the specified types in this case (item1: LIST_OF_GUID, GUID)
But you can use this with any type of constrains

Sorting a dictionary by keys in the order in an Arraylist

I was asked the following question in an interview. How can I sort a Dictionary by the key, in the order which is in an array list.
So for example I have a dictionary as follows
Dictionary<string, string> stringDict = new Dictionary<string, string>();
stringDict.Add("1", "One");
stringDict.Add("7", "Seven");
stringDict.Add("6", "Six");
stringDict.Add("2", "Two");
stringDict.Add("3", "Three");
stringDict.Add("5", "Five");
stringDict.Add("4", "Four");
And an array list as follows
ArrayList stringArList = new ArrayList();
stringArList.Add("1");
stringArList.Add("2");
stringArList.Add("3");
stringArList.Add("5");
stringArList.Add("6");
stringArList.Add("7");
stringArList.Add("4");
How can I sort the dictionary in the order it is in the array list?
Well you can't sort a Dictionary per se, but you can extract the key-values pairs as a list and sort those:
IEnumerable<KeyValuePair<string, string>> pairs =
stringDict.OrderBy(kvp => stringArList.IndexOf(kvp.Key));
But there's not a way to "traverse" dictionary items in any particular order.
You could create a SortedDictionary and provide an IComparer<string>
var d = new SortedDictionary<string, string>(stringDict,
new PositionComparer(stringArList));
With the Comparer implementation as:
public class PositionComparer : IComparer<string>
{
private ArrayList Keys {get; set;}
public PositionComparer(ArrayList keys)
{
Keys = keys;
}
public int Compare(string s1, string s2)
{
return Keys.IndexOf(s1).CompareTo(Keys.IndexOf(s2));
}
}
This will produce a list of the values sorted as required.
var sortedValues = stringDict.OrderBy(pair => stringArList.IndexOf(pair.Key))
.Select(pair => pair.Value)
.ToList();
As said many times before in this question, a C# Dictionary can not be sorted. This is inherent to the implementation. As you can read here, the dictionary is implemented using a Hashtable. This means that those items don't have any ordering. You can't say "give me the first element of this dictionary". There simply is no first, second or last element. The only thing you can say about an element in a dictionary is that it has a unique identifier which determines it's location in the dictionary (with a little help from the hash function).
When you have an element in an array for example, you can say "this element is the next element" or "this element is the previous element". Each element in an array has a previous and a next. This does not hold for dictionaries.
When you insert an item into the dictionary it will generate a hash (a fairly unique number) based on the key. For example, a very simple (and bad) hash of keys consisting of names would be to take the sum of each character presented as their ASCII value in the name, and then add those together. The result is a number, say 5, then we would insert the value in a store (an array for example) on position 5. If however, at position 5 is another value, which happens to have the same hash result you have a collision. How you solve these, and how you avoid these is what hashtables are all about. See the Wiki for more information on this.
When you request your value with your key someName it will hash that value and look it up at that position.
Hashtables are not as easy as I just explained, there is a lot too it. You can read more on the Wiki.
So the answer to "Sort this dictionary" is most definitely "No can do.". However, you can convert it to a sortable data structure like a list, or whatever and then sort it.
I replied with the following answer.
var list = from arElement in stringArList.ToArray().ToList()
join dict in stringDict on arElement equals dict.Key
select dict ;
But the interviewer didn't seem to be impressed.
original_dic.OrderBy returns IOrderedEnumerable, that you convert to a new dictionary.
var ordered_dic = original_dic.OrderBy(x => x.Key).ToDictionary(x=> x.Key, x=> x.Value);

How to get the value out of this type of dictionary in c#

I want to create, because I understand dictionaries are key=>value in C#, a dictionary that is much like key=>value(key=>value)
Currently I I know I can do:
Dictionary<int, int> someVar = new Dictionary<int, int>();
which creates me a key=>value.
To create what I want I could do (this is just a guess, please correct me if I am wrong):
Dictionary<int Dictionray<int, int>> someVar = new Dictionary<int, Dictionray<int, int>>
Now comes the fun part, I want to do ONE and only ONE for loop over this dictponary object YET get all values so it would look something like:
foreach (KeyValuePair<int, int> pair in someVar){
//object = base dictionary key
//object2 = nested dictionary key
//object3 = nested dictionary value
}
Now I come from PHP so this would be dead easy to do in one for loop. what are your ideas? because I am new to C# and the term dictionary (even though php arrays are dictionaries).
I know in C# with a for loop like this I could do: pair.Key and pair.Value.
My second part, is How do I add values to such a dictionary? I know the typical .add(bla, bla) but how do you add values to the nested part?
Iterating
In C#, IDictionary<TKey, TValue> implements IEnumerable<KeyValuePair<TKey, TValue>>. So, you can iterate over an instance of type IDictionary<TKey, TValue> using foreach or a Linq query, and get every KeyValuePair in the data structure. Since your TValue is in this case itself an IDictionary, you can do this on the inner structure as well:
foreach(var kvp in myDictionary)
{
foreach(var innerKvp in kvp.Value)
{
var myValue = innerKvp.Value
//Logic on myValue
}
}
Using the Linq library, you can use SelectMany to get all of the KeyValuePair instances quite elegantly:
myDictionary.SelectMany(kvp => kvp.Value);
SelectMany essentially flattens a list of lists. This Linq query is saying: for each key value pair in my dictionary, get all the inner dictionaries, treat them as lists of key value pairs, and then flatten all those lists. This will return an IEnumerable<KeyValuePair<TKey, TValue>>.
If instead you only care about the values of the inner dictionary, and not the keys, you can use the Values property on IDictionary<TKey, TValue> which returns an IEnumerable<TValue> of all the values in the dictionary. We can then use SelectMany to get a list that contains all the values in the dictionary of dictionaries:
myDictionary.Values.SelectMany(dict => dict.Values);
Read more about IDictionary<TKey, TValue> here and more about KeyValuePair<TKey, TValue> here.
Adding
In order to add an element to this data structure, you'll have to first check if the inner dictionaries are null. Let's say we're trying to add 3 to the dictionary keyed by 2 in the dictionary keyed by 1:
var myInnerDictionary = myDictionary.ContainsKey(1) ? myDictionary[1] : (myDictionary[1] = new Dictionary<int, int>());
myInnerDictionary[1][2] = 3;
Of course this will override a value in that location if it already exists, so you might want to check that as well, or use the Add method, which will not overwrite.
You should also learn about the ToDictionary Linq method which can help you construct dictionaries from other IEnumerables. Read about it here.
use linq to get all the values
var values = someVar.SelectMany(x => x.Values);
as for how to add values to the nested part, you'd just need the key for the outer dictionary for which sub dictionary you want to to add it to:
someVar[key].Add(0, 0);
It's impossible to get all the values including nested by using only one foreach loop, unless nested Dictionaries have a values which you can get without using loop, like this:
foreach (var pair in someVar){
var object1 = (Dictionary<int,int>)pair.Value;
var object2 = object1[0].Value;
var object3 = object1[1].Value;
.....
// To add a values to the nested Dictionary just use Dictionary.Add method:
object1.Add(1,1);
}

Store non-unique pairs in .net 2.0?

I have to store a pair of strings that are non-unique, so I could have something like:
"A", "B"
"A","C"
I can't use a Dictionary or HashTable because I don't have a unique key. I thought about a couple options:
List<List<string>,List<string>> = new List<List<string>,List<string>>(); //Too long?
Create a class or struct (what is better?) to hold my pairs and then store that in list, so
class pairs
{
}
List<pairs> values = new List<pairs>();
I also just need to be able to enumerate through the pairs, so I don't need care about querying, sorting, comparing. Because of this, is it best to use the least specific type, such as Enumerable?
You should be able to use a List<KeyValuePair<string, string>>.
KeyValuePair<TKey, TValue> structs by themselves don't require unique keys, even if you collect them in a single list.
If you think KVPs don't ring well semantically with what you want, just go with a custom type. It shouldn't matter whether your custom type is a class or struct.
What about just a List<string[]>?
var list = new List<string[]>();
list.Add(new [] { "A", "B"});
foreach(var pair in list)
{
Console.WriteLine(pair[0] + pair[1]);
}
You could use a List<KeyValuePair<string,string>>, but to avoid the semantics of a key (since you said it wasn't unique), I would use a List<Tuple<string,string>> which is practically the same but with different semantics.

SortedSet and SortedList fails with different enums

The whole story; I have some KeyValuePairs that I need to store in a session and my primary goal is to keep it small. Therefore I don't have the option of using many different collection. While the key is a different enum value of of a different enum type the value is always just a enum value of the same enum type. I have chosen a HashTable for this approach which content look like this (just many more):
// The Key-Value-Pairs
{ EnumTypA.ValueA1, MyEnum.ValueA },
{ EnumTypB.ValueB1, MyEnum.ValueB },
{ EnumTypC.ValueC1, MyEnum.ValueA },
{ EnumTypA.ValueA2, MyEnum.ValueC },
{ EnumTypB.ValueB1, MyEnum.ValueC }
At most I am running contains on that HashTable but for sure I also need to fetch the value at some point and I need to loop through all elements. That all works fine but now I have a new requirement to keep the order I have added them to the HashTable -> BANG
A HashTable is a map and that is not possible!
Now I thought about using a SortedList<object, MyEnum> or to go with more Data but slightly faster lookups and use a SortedSet<object> in addition to the HashTable.
Content below has been edited
The SortedList is implemented as
SortedList<Enum, MyEnum> mySortedList = new SortedList<Enum, MyEnum>();
the SortedSet is implemented as
SortedSet<Enum> mySortedSet = new SortedSet<Enum>();
The described Key - Value - Pairs are added to the sorted list with
void AddPair(Enum key, MyEnum value)
{
mySortedList.Add(key, value);
}
And for the SortedSett like this
void AddPair(Enum key)
{
mySortedSet.Add(key);
}
Both are failing with the exception:
Object must be the same type as the
enum
My question is: What goes wrong and how can I archive my goal?
Used Solution
I've decided to life with the downside
of redundant data against slower
lookups and decided to implement a
List<Enum> which will retain the
insert order parallel to my already
existing HashTable.
In my case I just have about 50-150
Elements so I decided to benchmark the
Hashtable against the
List<KeyValuePair<object,object>>
Therefore I have create me the
following helper to implement
ContainsKey() to the
List<KeyValuePair<object,object>>
static bool ContainsKey(this List<KeyValuePair<object, object>> list, object key)
{
foreach (KeyValuePair<object, object> p in list)
{
if (p.Key.Equals(key))
return true;
}
return false;
}
I inserted the same 100 Entries and
checked randomly for one of ten
different entries in a 300000 loop.
And... the difference was tiny so I
decided to go with the
List<KeyValuePair<object,object>>
I think you should store your data in an instance of List<KeyValuePair<Enum, MyEnum>> or Dictionary<Enum, MyEnum>.
SortedSet and SortedList are generic, but your keys are EnumTypeA/EnumTypeB, you need to specify the generic T with their base class(System.Enum) like:
SortedList<Enum, MyEnum> sorted = new SortedList<Enum, MyEnum>();
EDIT
Why you got this exception
SortedList and SortedSet use a comparer inside to check if two keys are equal. Comparer<Enum>.Default will be used as the comparer if you didn't specify the comparer in the constructor. Unfortunately Comparer<Enum>.Default isn't implemented as you expected. It throws the exception if the two enums are not the same type.
How to resolve the problem
If you don't want to use a List<KeyValuePair<Enum, MyEnum>> and insist using SortedLIst, you need to specify a comparer to the constructor like this:
class EnumComparer : IComparer<Enum>
{
public int Compare(Enum x, Enum y)
{
return x.GetHashCode() - y.GetHashCode();
}
}
var sorted = new SortedList<Enum, MyEnum>(new EnumComparer());
Btw, I think you need to obtain the "inserting order"? If so, List<KeyValuePair<K,V>> is a better choice, because SortedSet will prevent duplicated items.

Categories

Resources