issue while getting values from Dictionary<int, List<int>> - c#

I am having a dictionary which was defined as follows
Dictionary<int, List<int>> dict1 = new Dictionary<int, List<int>>();
I will have a list element where i can store the values which will come from database
List<int> lstdbTaskID = new List<int>();
assume this holds
100 105 110 200
respectively.
I will have my dictionary with values stored as follows. Assume that i have 2 keys 10,20 respectively, and for this key values i will have my values as for 10 i will have 100,105 and 110 and for 20 i will have 200.
I would like to compare these values with the list available lstdbTaskID
I tried this
foreach (int strlst in lstdbTaskID)
{
if (dict1.ContainsValue(lstdbTaskID[strlst]))
}
But i am getting errors as follows
The best overloaded method match for 'System.Collections.Generic.Dictionary>.ContainsValue(System.Collections.Generic.List)' has some invalid arguments`
and
Cannot convert from 'int' to 'System.Collections.Generic.List'`
can any help me on this?

Your code is wrong at because you are trying to compare int value with List of int.
Your dictionary is:
Dictionary of int to List of int.
and you have another structure as
List of int
so when you do:
// Compiler fails here because you are trying to check whether dictionary contains
// the given integer value. Dictionary in this case has a list of integers as its `Value`
// in its `<Key,Value>` pair.
dict1.ContainsValue(lstdbTaskID[strlst])
Use linq statement:
foreach (int strlst in lstdbTaskID)
{
if (dict1.Any(pair => pair.Value.Contains(strlst)))
{
// do something
}
}
Edit: If you want this without linq, do the linq task by self.
foreach (int strlst in lstdbTaskID)
{
foreach (int key in dict1.Keys)
{
if (dict1[key].Contains(strlst))
{
// do something
}
}
}

Look at the type of the value you're storing in your dictionary - it's a List<int>, not an int. So it makes no sense to ask whether the dictionary contains a value of 5, say.
However, it does make sense to ask if the dictionary contains any value (list) which itself contains 5.
For example:
foreach (int strlst in lstdbTaskID)
{
if (dict1.Values.Any(list => list.Contains(strlst))
{
...
}
}
However, that's really not a very efficient way of representing it. It's not clear what the best of representing it is though, without knowing what you're going to do with the results. You may just want a HashSet<int> containing all the values from all the lists, for example - but if you want to get back to the keys whose values contained a particular ID, that's a different matter.
EDIT: In .NET 2.0 land, you could use:
foreach (int strlst in lstdbTaskID)
{
foreach (List<int> list in dict1.Values)
{
if (list.Contains(strlst))
}
}
... but you're really not using the dictionary as a dictionary in either case here...

I am having slight problems understanding your question fully, however, my answer should push you in the right direction. Seeing as you do not have access to Linq (as you are using .Net 2.0):
static bool IsContained(IEnumerable<int> lstdbTaskID, Dictionary<int, HashSet<int>> dict1)
{
foreach (int strlst in lstdbTaskID)
foreach (HashSet<int> value in dict1.Values)
if (value != null && value.Contains(strlst))
return true;
return false;
}
You should use a HashSet<int> as it is far faster for looking up values (and is supported in .Net 2.0); however, you should not use HashSet<int> (and instead use List<int>) if:
The list needs to store duplicates.
- or - The order of the values is important.

Well, dict1 is a dictionary of dictionaries, not ints. So dict1.ContainsValue takes a dictionary as a parameter - you're checking whether it contains a given dictionary or not. But you're giving it an int.
Try this:
if (dict1.Any(x => x.Value.ContainsValue(strlst))) // ...

Related

How do I check if a list contains a tuple in C#

Before adding a new tuple, I want to check if a list already contains that tuple and avoiding adding it to the list again, how would I got about doing this? I'm aware for integers and strings you would just write list.Contains(2) or list.Contains("2"), but i'm not sure what syntax to use when checking for tuples.
I've tried these two so far (snippets). (combination is a list of tuples<char, char>)
if(!combinations.Contains(Tuple<char, char>(s[i], chr)))
{
combinations.Add(new Tuple<char, char>(s[i], chr));
}
if(!combinations.Contains(Tuple<char, char> s[i], chr))
{
combinations.Add(new Tuple<char, char>(s[i], chr));
}
Adding works fine so I thought it would be the same when comparing. Any help with syntax or logic would be great, thanks :)
Tuples already implement the appropriate equality, so you shouldn't need to do anything except create the value, and then use .Contains. However:
you may prefer ValueTuple<...> over Tuple<...>, and
if order doesn't matter, you may prefer HashSet<T>, which handles uniqueness internally
For example:
// note that (char, char) is a ValueTuple<char, char>
private readonly HashSet<(char,char)> combinations = new();
//...
combinations.Add((x, y)); // adds the x/y tuple if it doesn't exist
You can also name the parts here:
private readonly HashSet<(char X,char Y)> combinations = new();
which will allow you to use .X and .Y on values, via compiler voodoo.
In C#, you can use the Contains() method to check if a list contains a specific tuple. Here is an example:
// List of tuples
var tupleList = new List<(char, char)>()
{
('a', 'b'),
('c', 'd'),
('e', 'f')
};
// Tuple to search for
var searchTuple = ('a', 'b');
// Check if the list contains the tuple
if (tupleList.Contains(searchTuple))
{
Console.WriteLine("The list contains the tuple");
}
else
{
Console.WriteLine("The list does not contain the tuple");
}

Dictionary Unhandled Exception in C#: "The given key was not present in the dictionary"

I'm trying to print out a dictionary in C# that will simulate a graph. My dictionary looks like this:
Dictionary<int, List<int>> graph = new Dictionary<int, List<int>>();
In main, I add something to the dictionary, then try to print it out:
dicOfLists myDic = new dicOfLists();
myDic.AddEdge(1, 2);
myDic.printList();
The methods AddEdge and PrintList are pretty straightforward:
AddEdge:
public void AddEdge(int v1, int v2)
{
if (graph[v1] == null)
{
graph[v1] = new List<int> { v2 };
return;
}
graph[v1].Add(v2);
}
PrintList:
for (int i = 0; i < 1; i++)
{
Console.WriteLine(graph[i][i]);
}
I haven't done much programming in C# or Python, so dictionaries are new to me. I think why I'm getting tripped up is more conceptual than anything, specifically because I'm not sure how a list works within a dictionary.
The way I currently understand it is as follows:
Upon calling Addedge(1, 2) my dictionary is creating a list with a single element 2 at position 1 of my dictionary. This is because the first parameter represents the dictionary's key, and the second represents the list. The key functions like it would in a hashtable. When the key is provided, the dictionary looks at that position, and then creates a list.
Like I said, I'm new to C# so please don't skewer me too hard. While this might be something trivial like a straightforward syntax error, I'm not able to find much of anything for this specific problem online. Any help would be greatly appreciated!
You've got one method adding key/values to a dictionary and another printing them. The method printing them doesn't "know" what's been inserted, so it's better if that method doesn't make any assumptions about what's in the dictionary. Instead of just looping through a series of possible keys (0 to 1, 0 to n, etc.) it's better to operate according to what actually is in the dictionary.
var keys = graph.Keys;
// or, if you they were entered out of sequence and you want to sort them
var keys = graph.Keys.OrderBy(k => k);
// Now you're using the actual keys that are in the dictionary, so you'll never
// try to access a missing key.
foreach(var key in keys)
{
// It's not quite as clear to me what you're doing with these objects.
// Suppose you wanted to print out everything:
Console.WriteLine($"Key: {key}");
foreach(var value in graph[key])
{
Console.WriteLine(value);
}
}

How to get the last value entered [duplicate]

My dictionary:
Dictionary<double, string> dic = new Dictionary<double, string>();
How can I return the last element in my dictionary?
What do you mean by Last? Do you mean Last value added?
The Dictionary<TKey,TValue> class is an unordered collection. Adding and removing items can change what is considered to be the first and last element. Hence there is no way to get the Last element added.
There is an ordered dictionary class available in the form of SortedDictionary<TKey,TValue>. But this will be ordered based on comparison of the keys and not the order in which values were added.
EDIT
Several people have mentioned using the following LINQ style approach
var last = dictionary.Values.Last();
Be very wary about using this method. It will return the last value in the Values collection. This may or may not be the last value you added to the Dictionary. It's probably as likely to not be as it is to be.
Dictionaries are unordered collections - as such, there is no concept of a first or last element. If you are looking for a class that behaves like a dictionary but maintains the insertion order of items, consider using OrderedDictionary.
If you are looking for a collection that sorts the items, consider using SortedDictionary<TKey,TValue>.
If you have an existing dictionary, and you are looking for the 'last' element given some sort order, you could use linq to sort the collection, something like:
myDictionary.Values.OrderBy( x => x.Key ).Last();
By wary of using Dictionary.Keys.Last() - while the key list is sorted using the default IComparer for the type of the key, the value you get may not be the value you expect.
I know this question is too old to get any upvotes, but I didn't like any of the answers so will post my own in the hopes of offering another option to future readers.
Assuming you want the highest key value in a dictionary, not the last inserted:
The following did not work for me on .NET 4.0:
myDictionary.Values.OrderBy( x => x.Key ).Last();
I suspect the problem is that the 'x' represents a value in the dictionary, and a value has no key (the dictionary stores the key, the dictionary values do not). I may also be making a mistake in my usage of the technique.
Either way, this solution would be slow for large dictionaries, probably O(n log n) for CS folks, because it is sorting the entire dictionary just to get one entry. That's like rearranging your entire DVD collection just to find one specific movie.
var lastDicVal = dic.Values.Last();
is well established as a bad idea. In practice, this solution may return the last value added to the dictionary (not the highest key value), but in software engineering terms that is meaningless and should not be relied upon. Even if it works every time for the rest of eternity, it represents a time bomb in your code that depends on library implementation detail.
My solution is as follows:
var lastValue = dic[dic.Keys.Max()];
The Keys.max() function is much faster than sorting O(n) instead of O(n log n).
If performance is important enough that even O(n) is too slow, the last inserted key can be tracked in a separate variable used to replace dic.Keys.Max(), which will make the entire lookup as fast as it can be, or O(1).
Note: Use of double or float as a key is not best practice and can yield surprising results which are beyond the scope of this post. Read about "epsilon" in the context of float/double values.
If you're using .NET 3.5, look at:
dic.Keys.Last()
If you want a predictable order, though, use:
IDictionary<int, string> dic = new SortedDictionary<int, string>();
Instead of using:
Dictionary<double, string>
...you could use:
List<KeyValuePair<double, string>>
This would allow you to use the indexer to access the element by order instead of by key.
Consider creating a custom collection that contains a reference in the Add method of the custom collection. This would set a private field containing the last added key/value(or both) depending on your requirements.
Then have a Last() method that returns this. Here's a proof of concept class to show what I mean (please don't knock the lack of interface implementation etc- it is sample code):
public class LastDictionary<TKey, TValue>
{
private Dictionary<TKey, TValue> dict;
public LastDictionary()
{
dict = new Dictionary<TKey, TValue>();
}
public void Add(TKey key, TValue value)
{
LastKey = key;
LastValue = value;
dict.Add(key, value);
}
public TKey LastKey
{
get; private set;
}
public TValue LastValue
{
get; private set;
}
}
From the docs:
For purposes of enumeration, each item
in the dictionary is treated as a
KeyValuePair structure representing a
value and its key. The order in which
the items are returned is undefined.
So, I don't think you can rely on Dictionary to return the last element.
Use another collection. Maybe SortedDictionary ...
If you just want the value, this should work (assuming you can use LINQ):
dic.Values.Last()
You could use:
dic.Last()
But a dictionary doesn't really have a last element (the pairs inside aren't ordered in any particular way). The last item will always be the same, but it's not obvious which element it might be.
With .Net 3.5:
string lastItem = dic.Values.Last()
string lastKey = dic.Keys.Last()
...but keep in mind that a dictionary is not ordered, so you can't count on the fact that the values will remain in the same order.
A dictionary isn't meant to be accessed in order, so first, last have no meaning. Do you want the value indexed by the highest key?
Dictionary<double, string> dic = new Dictionary<double, string>();
double highest = double.MinValue;
string result = null;
foreach(double d in dic.keys)
{
if(d > highest)
{
result = dic[d];
highest = d;
}
}
Instead of using Linq like most of the other answers suggest, you can just access the last element of any Collection object via the Count property (see ICollection.Count Property for more information).
See the code here for an example of how to use count to access the final element in any Collection (including a Dictionary):
Dictionary<double, string> dic = new Dictionary<double, string>();
var lastElementIndex = dic.Count - 1;
var lastElement = dic[lastElementIndex];
Keep in mind that this returns the last VALUE, not the key.

Search for an existing object in a list

This is my first question here so I hope I'm doing right.
I have to create a List of array of integer:
List<int[]> finalList = new List<int[]>();
in order to store all the combinations of K elements with N numbers.
For example:
N=5, K=2 => {1,2},{1,3},{1,4},...
Everything is all right but I want to avoid the repetitions of the same combination in the list({1,2} and {2,1} for example). So before adding the tmpArray (where I temporally store the new combination) in the list, I want to check if it's already stored.
Here it's what I'm doing:
create the tmpArray with the next combination (OK)
sort tmpArray (OK)
check if the List already contains tmpArray with the following code:
if (!finalList.Contains(tmpArray))
finalList.Add(tmpArray);
but it doesn't work. Can anyone help me with this issue?
Array is a reference type - your Contains query will not do what you want (compare all members in order).
You may use something like this:
if (!finalList.Any(x => x.SequenceEqual(tmpArray))
{
finalList.Add(tmpArray);
}
(Make sure you add a using System.Linq to the top of your file)
I suggest you learn more about value vs. reference types, Linq and C# data structure fundamentals. While above query should work it will be slow - O(n*m) where n = number of arrays in finalList and m length of each array.
For larger arrays some precomputing (e.g. a hashcode for each of the arrays) that allows you a faster comparison might be beneficial.
If I remember correctly, contains will either check the value for value data types or it will check the address for object types. An array is an object type, so the contains is only checking if the address in memory is stored in your list. You'll have to check each item in this list and perform some type of algorithm to check that the values of the array are in the list.
Linq, Lambda, or brute force checking comes to mind.
BrokenGlass gives a good suggestion with Linq and Lambda.
Brute Force:
bool itemExists = true;
foreach (int[] ints in finalList)
{
if (ints.Length != tmpArray.Length)
{
itemExists = false;
break;
}
else
{
// Compare each element
for (int i = 0; i < tmpArray.Length; i++)
{
if (ints[i] != tmpArray[i])
{
itemExists = false;
break;
}
}
// Have to check to break from the foreach loop
if (itemExists == false)
{
break;
}
}
}
if (itemExists == false)
{
finalList.add(tmpArray);
}

swapping two key/value pairs in Dictionary of C#

here is what I want to do.
there is a Dictionary having 54 key/value objects. I want the key/value pair at index i to be swapped with the key/value pair at index j...
int i=1; int j=3;
Dictionary<String, int> theDeck = new Dictionary<String, int>();
theDeck.Add("zero", 0);
theDeck.Add("one", 1);
theDeck.Add("two", 2);
theDeck.Add("three", 3);
KeyValuePair<String, int> p1 = theDeck.ElementAt(i);
KeyValuePair<String, int> p2 = theDeck.ElementAt(j);
theDeck.ElementAt(i) = p2; //THIS LINE DOES NOT WORK. WHAT IS ITS ALTERNATIVE
theDeck.ElementAt(j) = p1; //THIS LINE DOES NOT WORK. WHAT IS ITS ALTERNATIVE
Dictionary<,> instances don't have "indexes" - you shouldn't treat them as ordered at all. Any order you may happen to notice when iterating over entries should be seen as an implementation detail.
If you want a specific order, there are various different types you could use, depending on your requirements. For example, to sort based on the key you'd use SortedDictionary<,> or SortedList<,>. For arbitrary ordering, consider OrderedDictionary (which is unfortunately non-generic).
Do you definitely need a dictionary at all? Could you just use a List<KeyValuePair<string, int>> or perhaps a List<Card> where Card is a custom type? (I'm guessing at your use case - Card could be any type which represents everything in your entry.)
Make mirroring (the 2nd) dictionary, and use it as a key source. Combine in 3d dictionary, while processing.
Try this.This worked for me.
First convert dictionary to list then find indexes of objects to be swapped.After swapping convert list back to dictionary.
var list = someDictionary.ToList();
int indexA = list.FindIndex(objA=> (condition));
int indexB = list.FindIndex(objB => (condition));
list.SwapListEntries(indexA, indexB);
someDictionary=list.ToDictionary(obj => obj.Key, obj => obj.Value);

Categories

Resources