Vba Type-Statement conversion to C# - c#

This can probably be accomplished very easily but I have the following statement in VBA:
Type testType
integerArray(5 To 100) As Double
End Type
How can I accomplish the same in C#?
#Edit 14:16 08-07-2015
In my belief this is not the same as the question mentioned. This is a question how to convert the Type statement with an array inside. The question mentioned is only about an array with it's starting index.

Actually C# does not support those kind of arrays based on any other start-index then zero.
However you may do.
double[] myArray = new double[96];
Alternatvily you may create a dictionary with indexes as keys and the actual value:
var myDict = new Dictionary<int, double>();

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

Convert IList to array in C#

I want to convert IList to array:
Please see my code:
IList list = new ArrayList();
list.Add(1);
Array array = new Array[list.Count];
list.CopyTo(array, 0);
Why I get System.InvalidCastException : At least one element in the source array could not be cast down to the destination array type? How that can be resolved assuming I can not use ArrayList as type for list variable ?
Update 1: I use .NET 1.1. So I can not use Generics, Linq and so on. I just want to receive result for the most common case - integer was given as example, I need this code works for all types so I use Array here (maybe I am wrong about using Array but I need, once again, common case).
You're creating an array of Array values. 1 is an int, not an Array. You should have:
IList list = new ArrayList();
list.Add(1);
Array array = new int[list.Count];
list.CopyTo(array, 0);
or, ideally, don't use the non-generic types to start with... use List instead of ArrayList, IList<T> instead of IList etc.
EDIT: Note that the third line could easily be:
Array array = new object[list.Count];
instead.
You can use Cast and ToArray:
Array array = list.Cast<int>().ToArray();
I'm surprised that
Array array = new Array[list.Count];
even compiles but it does not do what you want it to. Use
object[] array = new object[list.Count];
And, standard remark: if you can use C#3 or later, avoid ArrayList as much as possible. You'll probably be happier with a List<int>
probably the most compact solution is this:
Enumerable.Range(0, list.Count).Select(i => list[i]).ToArray();

Generics in C#, Dictionary<TKey,TValue>

I started reading C# in depth. Now I'm in the journey of Generics. I came across the first example of Generics in this book as:
static Dictionary<string,int> CountWords(string text)
{
Dictionary<string,int> frequencies;
frequencies = new Dictionary<string,int>();
... //other code goes here..
And after this code, author says that:
The CountWords method first creates an empty map from string to int
This looks vague to me, as a novice in C#, what the author is trying to mean string to int(in the above statement)? I'm bit confused with this line.
Thanks in advance.
Lets say we want to count the words in a paragraph:
I started reading C# in depth. Now I am in the journey of Generics.
I came across the first example of Generics in this book as
In order to count the words, you'll need some data structure that will be able to store a number of occurrences for each of the words, that will basically attach a number to a string, like
I - 3 times
in - 3 times
Generics - 2 times
etc...
that structure maps a string to an integer, and in C# Generics, that structure is a Dictionary<string,int>
BTW, if you are a C# beginner, i would recommend against C# in depth, which, while being a great book, assumes a quite advanced reader.
He means that string is your key and int is the value paired with the key.
Dictionary<string,int> maps a string key (or lookup) to an int value.
Consider Dictionary<string,int> frequencies.
When you try to add an item you use (for example)
frequencies.Add("key3", 3)
When you add another item you cannot repeat "key3", because in Dictionary that's a unique key; so you create a "map" because you are sure you have unique keys and you can recall values using their key: frequencies["key3"]...
Dictionary<string, int> frequencies = new Dictionary<string, int>();
frequencies.Add("key3", 3);
frequencies.Add("key4", 4);
frequencies.Add("key3", 5); // This raises an error
int value = frequencies["key3"];
This function counts all words in a given string. In the returned dictionary exist for every found word one entry with the word as key. In the int value is stored, how many times this word was found in the string.
It means from the Key to the Value

Can you do $array["string"] in C# [duplicate]

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Set array key as string not int?
I know you can do something like
$array["string"] in php but can you also do something like this in C# instead of using arrays with numbers?
Arrays in PHP are in reality more like dictionaries in C#. So yes, you can do this, using a Dictionary<string, YourValueType>:
var dict = new Dictionary<string, int>();
dict["hello"] = 42;
dict["world"] = 12;
If you want to store key/value pairs, you could probably use a Dictionary:
http://msdn.microsoft.com/en-us/library/xfhwa508.aspx
In PHP the "array" class is actually a map, which is a data structure that maps values to keys.
In C# there are a lot of distinct data structure classes. Each with it's own characteristics.
Wikipedia is a good starting point to read about basic data structures in general:
http://en.wikipedia.org/wiki/Data_structure#Common_data_structures
Use Dictionary for this purpose :)
var dictionary = new Dictionary<string, string>();
dictionary["key"] = "value";
and so on
var ar = new string[]{"one", "two"};

Datastructures, C#: ~O(1) lookup with range keys?

I have a dataset. This dataset will serve a lookup table. Given a number, I should be able to lookup a corresponding value for that number.
The dataset (let's say its CSV) has a few caveats though. Instead of:
1,ABC
2,XYZ
3,LMN
The numbers are ranges (- being "through", not minus):
1-3,ABC // 1, 2, and 3 = ABC
4-8,XYZ // 4, 5, 6, 7, 8 = XYZ
11-11,LMN // 11 = LMN
All the numbers are signed ints. No ranges overlap with another ranges. There are some gaps; there are ranges that aren't defined in the dataset (like 9 and 10 in the last snippet above).
`
How might I model this dataset in C# so that I have the most-performant lookup while keeping my in-memory footprint low?
The only option I've come up with suffers from overconsumption of memory. Let's say my dataset is:
1-2,ABC
4-6,XYZ
Then I create a Dictionary<int,string>() whose key/values are:
1/ABC
2/ABC
4/XYZ
5/XYZ
6/XYZ
Now I have hash performance-lookup, but tons of wasted space in the hash table.
Any ideas? Maybe just use PLINQ instead and hope for good performance? ;)
If your dictionary is going to truly store a wide range of key values, an approach that expands all possible ranges into explicit keys will rapidly consume more memory than you likely have available.
You're best option is to use a data structure that supports some variation of binary search (or other O(log N) lookup technique). Here's a link to a generic RangeDictionary for .NET that uses an OrderedList internally, and has O(log N) performance.
Achieving constant-time O(1) lookup requires that you expand all ranges into explicit keys. This requires both a lot of memory, and can actually degrade performance when you need to split or insert a new range. This probably isn't what you want.
You can create a doubly-indirected lookup:
Dictionary<int, int> keys;
Dictionary<int, string> values;
Then store the data like this:
keys.Add(1, 1);
keys.Add(2, 1);
keys.Add(3, 1);
//...
keys.Add(11, 3);
values.Add(1, "ABC");
//...
values.Add(3, "LMN");
And then look the data up:
return values[keys[3]]; //returns "ABC"
I'm not sure how much memory footprint this will save with trivial strings, but once you get beyond "ABC" it should help.
EDIT
After Dan Tao's comment below, I went back and checked on what he was asking about. The following code:
var abc = "ABC";
var def = "ABC";
Console.WriteLine(ReferenceEquals(abc, def));
will write "True" to the console. Which means that the either the compiler or the runtime (clarification?) is maintaining the reference to "ABC", and assigns it as the value of both variables.
After reading up some more on Interned strings, if you're using string literals to populate the dictionary, or Interning computed strings, it will in fact take more space to implement my suggestion than the original dictionary would have taken. If you're not using Interned strings, then my solution should take less space.
FINAL EDIT
If you're treating your strings correctly, there should be no excess memory usage from the original Dictionary<int, string> because you can assign them to a variable and then assign that reference as the value (or, if you need to, because you can Intern them)
Just make sure your assignment code includes an intermediate variable assignment:
while (thereAreStringsLeftToAssign)
{
var theString = theStringToAssign;
foreach (var i in range)
{
strings.Add(i, theString);
}
}
As arootbeer has mentioned in his answer, the following code does not create multiple instances of the string "ABC"; rather, it interns a single instance and assigns a reference to that instance to each KeyValuePair<int, string> in dictionary:
var dictionary = new Dictionary<int, string>();
dictionary[0] = "ABC";
dictionary[1] = "ABC";
dictionary[2] = "ABC";
// etc.
OK, so in the case of string literals, you're only using one string instance per range of keys. Is there a scenario where this wouldn't be the case--that is, where you would be using a separate string instance for each key within the range (this is what I assume you're concerned about when you speak of "overconsumption of memory")?
Honestly, I don't think so. There are scenarios where multiple equivalent string instances may be created without the benefit of interning, yes. But I can't imagine these scenarios would affect what you're trying to do here.
My reasoning is this: you want to assign certain values to different ranges of keys, right? So any time you are defining a key-range-value pairing of this sort, you have a single value and several keys. The single part is what leads me to doubt that you'll ever have multiple instances of the same string, unless it is defined as the value for more than one range.
To illustrate: yes, the following code will instantiate two identical strings:
string x = "ABC";
Console.Write("Type 'ABC' and press Enter: ");
string y = Console.ReadLine();
Console.WriteLine(Equals(x, y));
Console.WriteLine(ReferenceEquals(x, y));
The above program, assuming the user follows instructions and types "ABC," outputs True, then False. So you might think, "Ah, so when a string is only provided at run-time, it isn't interned! So this could be where my values could be duplicated!"
But... again: I don't think so. It all comes back to the fact that you are going to be assigning a single value to a range of keys. So let's say your values come from user input; then your code would look something like this:
var dictionary = new Dictionary<int, string>();
int start, count;
GetRange(out start, out count);
string value = GetValue();
foreach (int key in Enumerable.Range(start, count))
{
// Look, you're using the same string instance to assign
// to each key... how could it be otherwise?
dictionary[key] = value;
}
Now, if you were actually thinking more along the lines of what LBushkin mentions in his answer--that you may potentially have huge ranges, making it impractical to define a KeyValuePair<int, string> for each key within that range (e.g., if you have a range of 1-1000000)--then I would agree that you're best off with some sort of data structure that bases its lookup on a binary search. If that's more your scenario, say so and I will be happy to offer more ideas on that front. (Or you could just take a look at the link LBushkin already posted.)
Use a balanced ordered tree (or something similar) mapping start-of-range to end-of-range and data. This will be easy to implement for non-overlapping ranges.
arootbeer has a good solution, but one you may find confusing to work with.
Another choice is to use a reference type instead of a string, so that you point to the same reference
class StringContainer {
public string Value { get; set; }
}
Dictionary<int, StringContainer> values;
var value1 = new StringContainer { Value = "ABC" };
values.Add(1, value1);
values.Add(2, value1);
They will both point to the same instance of StringContainer
EDIT: Thanks for the comments everyone. This method handles value types other than string, so it might be useful for more than the given example. Also, it is my understanding that strings don't always behave in the manner you would expect from reference values, but I could be wrong.

Categories