I have a textbox that I want to use to detect certain numbers (1 - 65) that have a value attached to them for doing math with the value.
Example: When a user types in the numerals "50" I want to associate that with the value 4500 (50, 4500).
So for each number 1 - 65 I want to assign a specific value, then when a user types a number 1 - 65 the program takes the associated value and assigns that to a variable so I can do math.
int lvl50 = 4500;
lvl50 = clvl;
tolvl = clvl - currentexp;
int ttlvl = (tlvl / ptexp) +1;
I'm looking for something like this.
I think you can use a Dictionary<int,int>
var values = new Dictionary<int,int> { { 1, 1000 }, { 50, 4500 } ... };
Then you can get the corresponding value of a number
values[50] // returns 4500
With user input:
var input = int.Parse(textBox1.Text);
var value = values[input];
Or use TryParse and ContainsKey methods to avoid possible exceptions
int input = -1;
if(int.TryParse(textBox1.Text, out input) && values.ContainsKey(input))
{
var value = values[input];
}
One of the methods I can think of is the use of a Dictionary<TKey, TValue> found under System.Collections.Generic;
values.Add(50, 4500);:
var values = new Dictionary<int, int>();
values.Add(50, 4500);
// ... etc
Create a formula/function:
If the numbers 1-65 values have any formula, than you can use create a method that will implement that formula value in order to use it.
Example:
public static int myFormula(int number)
{
return number * 90;
}
Dictionary:
If the following number matched values don't have any visible formula than you can use the Dictionary<int, int> to match them a specific value.
Example:
var myDic = Dictionary<int, int>() {
new { 1, 1 },
new { 50, 4500 },
};
From your code snippet, it looks (to me) like you may be calculating the value in the dictionary based on the key. You could place the logic for calculating the value in a separate method:
private int CalculateValue(int x)
{
// calculate value and return it
}
Then create a dictionary for a particular range of numbers like this:
var dict = Enumerable.Range(1, 65).ToDictionary(x => x, CalculateValue);
To use an element from the dictionary, just reference it using the key:
var matchingValue = dict[50]; // Lookup key 50
If it's possible the key may not exist, you can test for it:
var value = dict.ContainsKey(72) ? dict[72] : -1; // Assign some default value
Using a dictionary like the other answers suggest will work for you, but if your numbers 1-65 have no gaps, you can use a list (or even a simple array). The index of the list will be your input. That will be easier and more efficient than a dictionary.
var values = new List<int> { 1000 , 4500 };
Then you can get the corresponding value of user input:
int input, value;
if(int.TryParse(textBox1.Text, out input)){
if(values.Contains(input){
value = values[input];
}
}
Related
I am very new to programming and am taking an Object Oriented Programming class. However, the professor didn't explain how to take an Ienumerable and make it into a string in order to accomplish this question of the assignment:
TODO:
Write a public static C# method named NumSquare that takes a one-dimentional array as input
and creates a LINQ statement that queries the numbers that have a square number graeter than 20 and orders them ascending.
The LINQ query retrieves anonymous objects in which each object contains the number (Num) and its square number (SqrNum).
The method returns the LINQ query as an IEnumerable object.
The anonymous object contains two instance variables named Num and SqrNum.
Input: a one-dimentional integer array.
Output: a LINQ query of type IEnumerable.
Example: Given array A = [3, 4, 10, 5], invoking NumSquare(A) return a LINQ query that once executed will contain:
{Num=5, SqrNum=25},
{Num=10, SqrNum=25}
Here's what I have so far, but I've tried several things over the last 2 1/2 weeks.
public static IEnumerable<object> NumSquare(int[] A)
{
//write your code here
var num = from Number in A
select Number;
var sqrnum = from Number in A
let squarenum = Number * Number
select squarenum;
return (IEnumerable<object>)sqrnum;
}
I know that this return won't get me the whole result that I need, but that's as far as I can get with no errors. I also don't know how to test anything because he didn't show us how to call an IEnumerable. Help?
I think what you are looking for is not a string as output but as the exercise says an anonymous object. An anonymous object can be something like this:
var o = new { Num = 4, SqrNum = 16 };
Its just an object that basically has no explicit type and some read-only variables.
So what you want to do is to convert your array into a IEnumerable<{int Num, int SqrNum}> which you would have to declare as IEnumerable<object> and not a string.
You could do something like this:
static IEnumerable<object> NumSqr(int[] a)
{
return a
.Where(x => x * x > 20)
.OrderBy(x => x)
.Select(x => new { Num = x, SqrNum= x * x });
}
Alternatively:
static IEnumerable<object> NumSqr(int[] a)
{
return from number in a
where number * number > 20
orderby number
select new { Num = number, SqrNum = number * number };
}
In order to print out the result of the function you could do this:
var a = new int[] { 3, 4, 10, 5 };
var result = NumSqr(a);
foreach (var obj in result)
{
Console.WriteLine(obj);
}
The output should look like this:
{ Num = 5, SqrNum = 25 }
{ Num = 10, SqrNum = 100 }
I am implementing this code in my discord bot, where I want to be able to generate unique numbers from 1 to 10 (as suggested above) whenever I input a single command.
Turns out that the values sometimes are repeated. Therefore I was suggested to add an array (used[ ]) and a loop in order to check every time if the value has been generated already.
Random random = new Random();
int[] used = new int[10];
int rng = 0;
while (!used.Contains(rng))
{
rng = random.Next(1, 10);
}
/*
I wish to store the generated value "rng" to the "used" array.
e.g.
used[0] = rng
used[1] = rng
used[2] = rng
etc.
*/
Console.WriteLine("The number generated is " + Convert.ToString(rng));
However, I don't know how to constantly add values to an array in an arranged order. (as seen by the commentations above)
In a more simple way, For 10 times I want the system to generate a number, and those numbers are randomly picked out of [1,10] and only once. If all the numbers have been generated once, all are free to be generated again.
Sorry for my bad interpretation. I have refined it with the comments that everyone has contributed.
Here is a solution, that shuffles the values and returns each value until the list is exhausted, then starts all over:
int[] GenerateNewArray(int n)
{
// Define an array of values we wish to return and populate it
int[] baseValues = Enumerable.Range(1, n).ToArray();
Random rnd=new Random();
// Shuffle the array randomly using Linq
return baseValues.OrderBy(x => rnd.Next()).ToArray();
}
void Main()
{
int nNumbers = 10;
while (true)
{
// Generate a new randomized array
var values = GenerateNewArray(nNumbers);
// Print each value
for (int i=0;i<nNumbers;i++)
{
Console.WriteLine($"The number generated is {values[i]}");
}
}
}
EDIT
Parameterized the number of unique values.
Rather than storing in an array, looking for duplicates etc., just use a HashSet
This only accepts unique values, and if you try to add a duplicate it will be simply ignored.
Or you can just do a check to see if it exists
HashSet<int> integerSet = new HashSet<int>();
if (hashSet.Contains(rng ))
// element already exists in set
else
//Doesn't exist
Of course, if you just keep generating each number randomly until you have generated everything in the range, then you might as well just simply generate an array/list of elements with every number and save yourself processing time!
Using a list is a good way to start, but before continuing the comment go check out the list documentation
In small talk a list is an IEnumerable of a type you choose, in your case to declare and instanciate a list you should write like this List<int> listName = new List<int>(); and the main difference between an array and a list is that you can populate the list whenever you want without the length declaration, to do that you can add listName.Add(2); (2 : the integer value that you want to add) or remove values listName.Remove(0) (0 : the position of the list that need to be removed, ex: 0 is the first value inside the list because position 0 is the start)
Random random = new Random();
List<int> listName = new List<int>();
int rng = 0, counterOfValues = 0;
while (counterOfValues < 10)
{
rng = random.Next(1, 10);
If(!listName.Contains(rng))
{
listName.Add(rng);
Console.WriteLine("The number generated is " + listName.Last().ToString());
If(counterOfValues < 10)
{
counterOfValues++;
}
else
{
counterOfValues = 0;
}
}
}
This should probably do the work ("should" because it's some code I wrote out of my head, so sorry about caps ecc)
Let me know if it works as intended or we need to correct something!
P.S: If you want the user to select the range of the randomic values just change the value of counterOfValues in the lowest value and the 10's with the higher value
Using a HashSet is better to know the numbers that you are use. But in your case, I think it's better use a List and remove elements:
var list = new List<int>();
for (int i = 1; i <= 10; i++)
list.Add(i);
// List is 0-index
// list = 1 2 3 4 5 6 7 8 9 10
int rng = random.Next(0, list.Count - 1);
// Suppose rgn=3: You get 3 value and remove it from the list
var value = list[rgn];
list.RemoveAt(rgn);
// list = 1 2 4 5 6 7 8 9 10
// Now you get a value between 0...8 (list.Count is 9)
rng = random.Next(0, list.Count - 1);
// Suppose rgn=3: You get 4 value and remove it from the list
var value = list[rgn];
list.RemoveAt(rgn);
// list = 1 2 5 6 7 8 9 10
// Now you get a value between 0...7 (list.Count is 8)
rng = random.Next(0, list.Count - 1);
// Suppose rgn=5: You get 7 value and remove it from the list
var value = list[rgn];
list.RemoveAt(rgn);
// list = 1 2 5 6 8 9 10
...
When list has one element you don't need use random.
When your list is empty, fill again and repeat the whole process.
In this form you always get an element with each random call. Using HashSet you may try a lot of random calls to get a nonused number.
A class for that maybe:
public class RandomClass
{
private readonly List<int> _list;
private readonly Random _random;
public RandomClass()
{
this._list = new List<int>();
this._random = new Random();
}
private void PopulateList()
{
for (int i = 1; i <= 10; i++)
this._list.Add(i);
}
public int GetNumber()
{
if (this._list.Count == 0)
{
this.PopulateList();
}
if (this._list.Count > 1)
{
int rng = this._random.Next(0, this._list.Count);
var value = this._list[rgn];
this._list.RemoveAt(rgn);
return value;
}
else
{
var value = this._list[0];
this._list.RemoveAt(0);
return value;
}
}
}
UPDATE: Some about List, Arrays and other collections
Array and List are very similar. The main difference is that an array is a continuous block of memory while List (in memory) it's not a block. Array is faster to iterate (address of first element + multiply for sizeof each element) but slower when you want to add/remove elements (you must create other array and copy the elements). From the point of view of an user, both of them are used to store a list of items and iterate them.
Other collections very interesting are HashSet and Dictionary. These collections are sets, you can't access their elements using an index. You saw an example for HashSet in this page: Add a number to the set and query it if you want know if that number appear before. The key with this sets are that you access to their elements using a hash. Instead of an index, you use whatever you want as a key and an algorithm get quickly the position of the element in the set. Dictionary is like a HashSet but you can store addicional data asociated to the key.
In many cases, you'll use both of them: a list to iterate sequencially and a dictionary to direct access to elements. For example, you have a lot of Persons that you show in some order (name, surname...). You store them in a List an allow user to change the order (using Sort of the list). You use a list because you show and use that order many times: you need ordered Persons.
But you have many, many Persons. Suppose that your program allow search Persons by Id and Name. Each time a user search for Persons you must iterate a very long list. It's not efficient. So you define two Dictionary:
Dictionary<int, List<Person>> personsById;
Dictionary<string, List<Person>> personsByName;
Also, you have a List:
List<Person> allPersons;
And we need some operations:
public void AddPerson(Person person)
{
Person existingPerson;
if (personsById.TryGetValue(person.Id, out existingPerson))
{
// Already exists: don't add duplicated persons
return;
}
personsById.Add(person.Id, person);
// Maybe more than one person with the same name. It's the reason why use a List here
List<Person> list;
if (personsByName.TryGetValue(person.Name, out list))
{
// There are other persons with this name, so the list exists. Simply add person to list
list.Add(person);
}
else
{
// Is the first person with this name: create the list and associate to the name
personsByName.Add(person.Name, new List<Person> { person });
}
// Always add to main list
allPersons.Add(person);
}
public void RemovePerson(Person person)
{
if (!personsById.TryGetValue(person.Id, out _))
{
// Not exists: do nothing
return;
}
personsById.Remove(person.Id);
// NOTE: Here we are removing person assuming that you never have different instances
// of person. If you can create different instances for a person, here we must iterate
// the lists to find the person
List<Person> list;
if (personsByName.TryGetValue(person.Name, out list))
{
list.Remove(person);
}
allPersons.Remove(person);
}
public Person GetPerson(int id)
{
return this.personsById.TryGetValue(id, out Person person) ? person : null;
}
public List<Person> GetPersons(string name)
{
return this.personsByName.TryGetValue(name, out List<Person> list) ? list : null;
}
It's a very basic example but I think maybe a good one to learn about this classes.
I'm pretty sure this is something basic but for some reason I just can't seem to get it work. First I'm not sure which Collection Type I should be using. I'm using C# for my Unity game and I'd like to store info like this:
# Name Number Value
1 Jim 15
2 Bob 21
3 Tim 31
4 Ron 26
Numbers 1-4 would be indexes so if I removed entry #3 with Tim, the table would look like:
# Name Number Value
1 Jim 15
2 Bob 21
3 Ron 26
I assume I should be using Dictionaries and that's what I tried. What I want to do with my code is to pick a random element, print it and then remove it. Rinse and repeat until the list is empty.
This is what I've been using for my code:
Dictionary<String, int> myDictionary = new Dictionary<String, int> ();
void Start()
{
myDictionary.Add ("Jim", 15);
myDictionary.Add ("Bob", 21);
myDictionary.Add ("Tim", 31);
myDictionary.Add ("Ron", 26);
}
void Update()
{
int totalEntries = myDictionary.Count;
int randNumber = Random.Range(1,totalEntries);
print(myDictionary[randNumber]);
myDictionary.Remove(randNumber);
}
It's not working. I've seen some suggestions about using RemoveAt or using HashTable but I haven't been able to get those working either. RemoveAt for some reason isn't recognized as a command and HashTable just kind of had the same issue. I am using "using System.Collections.Generic;" btw so that's not the problem. I'd like to mention that I'm pretty new to C# so what would help me the most would be actual working code that I can then edit to fit my game.
A Dictionary would not be ideal in this case.
I'd use a List of Tuples (or a List of a custom class).
List<Tuple<int, String, int>> myItems = new List<Tuple<int, String, int>>();
void Start()
{
myItems.Add(Tuple.Create(1, "Jim", 15));
myItems.Add(Tuple.Create(2, "Bob", 21));
myItems.Add(Tuple.Create(3, "Tim", 31));
myItems.Add(Tuple.Create(4, "Ron", 26));
}
Now there are a couple of ways to identify the object you wish to remove. First your initial approach (by index in the list):
void Update()
{
var rnd = new Random();
var randNumber = rnd.Next(0, myItem.Count);
myItems.Remove(myItems.ElementAt(randNumber));
}
Then by the actual value of the object:
void Update2()
{
var minValue = myItems.Min(i => i.Item1); // Gets the minimum value in first column (so to speak);
var maxValue = myItems.Max(i => i.Item1); // Gets the maximum value.
var rnd = new Random();
var randNumber = rnd.Next(minValue, maxValue + 1); // maximum value in Random.Next is exclusive.
var myObject = myItems.SingleOrDefault(o => o.Item1 == randNumber);
if (myObject != null)
myItems.Remove(myObject);
}
Which method you prefer is up to you and the requirements to solve the task. You might prefer by index but on the other hand you might prefer removing by value.
The drawback by the second method is that you might not remove an object at all when the random value is already removed.
Try this:
using System.Linq;
var r = new Random();
var i = r.Next(0, dic.Count);
var e = dic.ElementAt(i)
dic.Remove(e);
create an array with the same length, and out in each cell a number 1 to N. and shuffle the array. then delete each row by index
I ended up finding this link: http://wiki.unity3d.com/index.php/Choosing_the_right_collection_type
And have been able to solve my issue with ArrayLists. This is the part of the link that really helped me:
ArrayList myArrayList = new ArrayList(); // declaration
myArrayList.Add(anItem); // add an item to the end of the array
myArrayList[i] = newValue; // change the value stored at position i
TheType thisItem = (TheType) myArray[i]; // retrieve an item from position i
myArray.RemoveAt(i); // remove an item from position i
var howBig = myArray.Count; // get the number of items in the ArrayList
Thanks everyone for all the sugestions!
How to check a single value is in a List. My List contains few random numbers: 13, 55, 34, 122, 322, 2132, 4345, 3000.
I want to have a bool check the list if it contains int 4 or any other number. List can have large numbers in three or four figures in the list.
It would be nice to guide me to design helper in webmatrix to provide bool results for this value check.
Try this,intVariable is your variable to search
bool isInList = intList.IndexOf(intVariable) != -1;
You can't get away without iteration (loop). Use Enumerable.Any(that uses iterator internally) for simplicity.
var ints = new int[] {1,2,3,4,5};
var any5 = ints.Any( i=> i== 5);
if the list is not that big why dont you loop inside the list
foreach(int a in MyList)
{
if(a == "that_value")
{
break;
}
}
I'm currently trying to create a program that estimates location based on signal strength. The signal strength value is an int and then i need a lookup dictionary with ranges.
So I would have something like:
Signal Strenth Position
0-9 1
10-19 2
20-29 3
and then I would want to look up what position a signal strength relates to, for example 15 would relate to position 2.
I know I can just have a load of if statements but is there a good way to do this using some sort of lookup dictionary?
If you have arbitrary but consecutive ranges you can use an array of the upper bounds and perform a binary search to get the position:
// Definition of ranges
int[] ranges = new int[] { 9, 19, 29 };
// Lookup
int position = Array.BinarySearch(ranges, 15);
if (position < 0)
position = ~position;
// Definition of range names
string[] names = new string[] { "home", "street", "city", "far away" };
Console.WriteLine("Position is: {0}", names[position]);
Array.BinarySearch returns the index of the item in the array if it exists (array must be sorted obviously) or the bitwise inverted index where the item should be inserted to keep the array sorted.
What about :
int position = signalStrength / 10 + 1;
Kindness,
Dan
When you want to use Dictionary, you need at least some special key type to deal with the ranges. KeyType can be abstract and two derived types KeyTypeRange(int int) and KEyTypeSearch( int). Some special comparison logic must be implemented to compare an KeyTypeSearch with an KeyTypeRange.
SortedDictionary<KeyType,int> lookup = new Dictionary<int,int>();
lookup.Add( new KeyTypeRange(1,10),1);
lookup.Add( new KeyTypeRange(11,20),2);
lookup.Add( new KeyTypeRange(21,30),3);
lookup.TryGetValue( new KeyTypeSearch(15) );
It shows a possible solution to use different esearch keys and key values in dictionaries. But this seems to be Overkill for this problem. This problem is solved best by the BinarySearch solution.
Good is a function of purpose. All of the above solutions work well presuming that any given range is a small number of integers. Otherwise you may want to use whatever the real world math function is to determine your group. For instance, for the example given, your answer function would be x % 10 + 1; That'll run much faster than a dictionary.
You could do a Dictionary, where the first int is the signal strength and the second int is the position. You would need to add an entry for every value in the range (so, one for signal strength 0, position 1, signal strength 1, position 1, etc.), but it would be a very quick, single line lookup.
Something like:
Dictionary<int, int> values;
values = new Dictionary<int, int>();
values[0] = 1;
values[1] = 1;
...
values[29] = 3;
and then, to access it:
Console.WriteLine(values[27].ToString());
For future expansion i would do 2 dictionaries.
Just in case those rates change
so a
dictionary<string,dictionary<int,int>>
or just use custom classes
the string would be static strings like low med, high, then you can change the ranges in your foreach initilixing the initial values
One solution would be to use a simple list, where each position in the list represents a different position that you're scanning for. In code, it might look something like this (assuming that all position numbers are sequential):
** Note: I have not actually run this code to make sure it works as-is... you might also need to implement an IEqualityComparer on Range in order for the IndexOf operation to return the proper position:
public class Controller
{
List m_positions = new List();
public void LoadPositions()
{
m_positions.Add(new Range(0, 9));
m_positions.Add(new Range(10, 19));
m_positions.Add(new Range(20, 29));
}
public int GetPosition (int signal)
{
Range range = m_positions.Single(a => IsBetween(signal, a.Min, a.Max));
return m_positions.IndexOf(range);
}
private static bool IsBetween (int target, int min, int max)
{
return min = target;
}
}
It's probably pretty self-explanatory, but to avoid any confusion, here's what the Range class might look like:
public class Range
{
public Range(int min, int max)
{
this.Min = min;
this.Max = max;
}
public int Min
{
get;
private set;
}
public int Max
{
get;
private set;
}
}
if there is a direct correlation between signal range and the position then use what #agileguy suggested.
If you have positions distributed non linearly across the signal strength then one way would be:
class SignalStrengthPositionMapper
{
private static readonly int[] signalStrength = { Int32.MinValue, 0, 5, 11, 15, 20, 27, 35 };
public static int GetPosition(int strength)
{
return StrengthSearch(0, signalStrength.Length, strength);
}
// modified binary search
private static int StrengthSearch(int start, int end, int strength)
{
int mid = 0;
while (start <= end)
{
mid = (start + end) / 2;
if (strength >= signalStrength[mid]) // lower bound check
{
start = mid + 1;
if (strength < signalStrength[start]) // upper bound check
return mid;
}
else if (strength < signalStrength[mid]) // upper bound check
{
end = mid - 1;
if (strength >= signalStrength[end]) // lower bound check
return mid;
}
}
return 0;
}
}
Try using generics:
Dictionary<int,int> lookup = new Dictionary<int,int>();
lookup.Add(0,1);
lookup.Add(1,1);
lookup.Add(2,1);
lookup.Add(3,1);
...
lookup.Add(9,1);
lookup.Add(10,2);
lookup.Add(11,2);
etc
Then, lookup[22] would return value of 3. I suggest using a set of loops to create your 'ranges'. With this method, you're guaranteed O(1) access time.