Create a list of tuples dynamically in C# - c#

I want to add to a C# list of tuples declared as
var myList = List<(int, int)>();
How can I do this? The method Add doesn't accept 2 arguments. The code computes 2 integers in a for loop. I want to check in each loop whether the generated 2 integers already exist in myList and, if not, add it to myList.

"The method Add doesn't accept 2 arguments"
Correct, but you can pass a Tuple<int, int> as a single argument to the list, since that's the type that the list contains.
"The code computes 2 integers in a for loop. I want to check in each loop whether the generated 2 integers already exist in myList and, if not, add it to myList"
Some code would help here, but I would suggest creating a Tuple<int, int> from the two integers and then checking if that tuple already exists in the list or not (Tuple overrides Equals to compare the values of it's items with the corresponding items in the other Tuple, so there's no extra work to do):
// We have two computed integers
int first = 5;
int second = 8;
// Add them as a Tuple to the list if it doesn't already exist
if (!myList.Contains((first, second))) myList.Add((first, second));

Related

Choosing a random element from a list of tuples C#

I'm quite new to programming and I am trying to add a random bot move to a small game I've made. My idea was to make a list of tuples of all of the legal moves and then pick a random tuple from that list to then deconstruct and change a value in a 2D-array.
I've looked all over the internet and found a way to make a list of tuples (I think), but couldn't manage to pick a random element from that list.
This is what I tried:
List<Tuple<int, int>> legalMoves; // To make the list of tuples
// Later on in a double for-loop that iterates through all the rows and columns of the 2D-array I check if that certain row and column combination is a legal move and then add it to the list like so:
legalMoves.Add(Tuple.Create(row, col));
//Then in a different method I try to pick a random element from that list (this doesn't work)
Random random = new Random();
int randomIndex = random.Next(legalMoves.Count);
(int, int) randomMove = legalMoves[randomIndex];
It gives the following error on the last line:
Error CS0029 Cannot implicitly convert type 'System.Tuple<int, int>' to '(int, int)'
Is there any way to make this work?
Thanks in advance!
The syntax (int, int) defines a ValueTuple<int,int> not a Tuple<int,int>. Change the list definition to :
List<ValueTuple<int, int>> legalMoves;
and Tuple.Create to ValueTuple.Create

Removing multiple items from ConcurrentDictionary based on conditional key

Let's say that I have a ConcurrentDictionary:
var dict = new ConcurrentDictionary<string, someObject>();
dict.TryAdd("0_someA_someB_someC", obj0);
dict.TryAdd("1_someA_someB_someC", obj1);
dict.TryAdd("2_someA_someB_someC", obj2);
dict.TryAdd("3_someA_someB_someC", obj3);
The <number>_ in the keys is incremented and being a dictionary, there is no guarantee that the elements are in order.
Now, imagine I wanted to remove all items from the dictionary that have the number less than 2. I have no idea what the keys will look like, only that they will be prefixed with a number as above.
How can I remove all elements from the dictionary who's key starts with a value less than 2?
For example, the resulting dict after this process will look like this:
dict.TryAdd("2_someA_someB_someC", obj2);
dict.TryAdd("3_someA_someB_someC", obj3);
Presuming it has always this format, you can use LINQ:
var keysToRemove = dict.Keys.Where(key => int.Parse(key.Remove(key.IndexOf('_'))) < 2).ToList();
keysToRemove.ForEach(key => dict.TryRemove(key, out someObject obj));
String.Remove removes the part starting from _ and then parses the remaiming first part, the number. It will only select the keys which number is lower than 2.
This list will be used to remove the items from the dictionary. Of course you need a lock to make this thread-safe.
Parse the number that comes before the first underscore (Tip: IndexOf and Substring)
Convert it to integer (Tip: int.TryParse)
Compare number to the value (2 in this case)
Filter the keys applying this method, store them in a collection. Iterate over the collection and call TryRemove method to remove entries associated with the key.
You would need to iterate across the dictionary collecting the keys that match the criteria and then iterate across that list of keys deleting from the dictionary. A for-each across a dictionary returns items with Key and Value properties, so you can examine the Key property to decide whether or not to delete. You cannot delete in the same loop as this will result in an error.
You could use Split to split the key into an array on the _ character, convert the first item in the resulting array into an int (note this will throw if the key doesn't start with an int), and if it's less than 2, remove it from the dictionary:
foreach (var item in dict.Where(kvp => int.Parse(kvp.Key.Split('_')[0]) < 2))
{
SomeObject tempObject;
dict.TryRemove(item.Key, out tempObject);
}

Storing lots of Arrays into a List on every Loop

I have a question about storing lots of arrays into a list.
First, I initialize the array and list:
int[] arr = new int[9];
List<int[]> forkarr = new List<int[]>();
then I run through a lot of for loops and modify the array each time in order to produce all possible tic tac toe variations. While looping through all those variations, if the array is a possible board then I print it, and additionally if the array meets certain criteria for being a 'fork', then I will add it to the list like this:
if (ForkCheck.fork(arr)) { forkarr.Add(arr); Console.WriteLine("It's a Fork!");}
which also prints that message letting you know that particular array is a fork.
Now, when I am printing all of the arrays, the ones that are forks are printed properly and labeled as such.
However, when I go to print out all of the int[] elements of my list forkarr like so:
foreach (int[] arry in forkarr)
{
PrintGame.print(arry);//this is my method that prints the array
Console.WriteLine();
}
for some reason each array becomes an identical:
222
222
222
(I'm using 2 as 'X' and 1 as 'O' and 0 as 'empty' btw)
And it just prints that out over and over for all the forks.
So, something is going wrong when I am adding each modification of the array as a new element in the list I think, but I'm not sure why.
Thanks for any help.
Because you are modifying the same array and adding it to the list. Each time you done with one array array you need to create a new instance like this:
arr = new int[9];
This will create a new reference which will be independent from other arrays. And modifying it's elements wont affect the others.
For more information about value vs reference types you can refer to the question below:
What is the difference between a reference type and value type in c#?

Value of items in a c# listbox

I am sure if i look hard enough i can find my answer but so far i can't find a clear cut answer.
What i am trying to do is use the value of an item in a listbox which contains 7 items as a numerical identifier for a specific array element. (all items in the list are strings)
array[listbox.value] = my new data for that array element
i know i can pull the string of the item out but and that i can identify a specific item in the list with.
list1.Items[value].ToString();
i just want to know if i can do reverse the alternative is a pain to code as its a lot more lines of code comparing the string in the list to each item in my array until i find a match while i know all items in the list are the same order as the array.
Instead of using an array, you can use a dictionary.
Dictionary<string, valueType> myArray = new Dictionary<string, valueType>();
myArray["Item1"] = some value
myArray["Item2"] = some value
... etc
Then later
myArray[listbox.Value.ToString()] = my new value
Thats really the best way to refer to an array index by a string value. The type for the indexer does not necessarily need to be a string, it can be any type that is uniquely identifiable.

how to find elements present in all three lists (most eficiently)

I use C# and I have three List<int> (say of equal size n and of distinct elements). My goal is to find elements present in all three. So I could iterate through first one and check if item is in the other two. That would be O(n^2). I could sort the other two lists first and then check for item in them using binary search. That would be O(nlogn) (without sorting).
Or I could construct two dictionaries Dictionary<int, byte>, where the key would be my list's item and then checking for an item would be O(1) and the total O(n). But how about the price of constructing dictionary? Can anyone tell how much does that cost?
Also perhaps there is even more efficient algorithm?
Using a HashSet is fairly simple, and I think it will be your best bet for performance.
HashSet<T> hset = new HashSet<T>(list1);
hset.IntersectWith(list2);
hset.IntersectWith(list3);
return hset.ToList(); // skip the ToList() if you don't explicitly need a List
You could use only one Dictionary<int, byte> where value of byte could be 1 or 2. For first list you just do the insert with value equal to 1, and for second list you do TryGetValue and based on result do either insert or update with value equal to 2. For third list you check if value is 2.

Categories