switch case from a list of integers ,code optimization - c#

i have a large switch case ,and i also have a list of integers say{1610616833,1610747905,1610878977,1610878977,1611010049}
i want to do the following
int a;
switch (incomingint)
{
case 1:
//some code
break;
case 2:
//some code
breakl
//now i want to check if this one is one of the list's integers or not
//so i did the following
case 1610616833:
a=0;
break;
case 1610747905:
a=1;
break;
case 1610878977:
a=2;
break;
}
The problem is :
I have around 16 element in the list
The code in the case of one of the list's members is almost the same except in the value i set for a .
NOTE:
setting the value of 'a' occurs only when the incomingint is one of the list members
so instead of writing all of that code, is there any way to optimize this code??

You could use a dictionary for this transformation:
Dictionary<int, int> transformation = new Dictionary<int, int>
{
{ 1000, 0 },
{ 1001, 1 },
// etc
};
int a = 0; // Default value
if (transformation.TryGetValue(incomingint, out a))
{
// a has the value. If you need to do something else, you might do it here because you know that dictionary had incomingint
}

You can create a dictionary that will be a mapping between your list items and values of a.
var dict = new Dictionary<int,int>();
dict.Add(1000, 0);
dict.Add(1001, 1);
dict.Add(1002, 5);
...
And later:
a = dict[incomingint];
If there is a direct way to compute a from incomingint, just use incomingint in the calculation. The data you posted looks like you could simply do:
a = incomingint - 1000;
For incomingint of values 1000 and above.

it seems like you can optimize this by writing
if (incomingint > 1000) a = incomingint - 1000;
in other news, if you have 16 ints in a list, you almost definitely don't need to optimize it. that's a tiny, blazing-fast amount of work.

Related

any way to use variables in c# switch case?

I know that case cannot work with non-constant values, but what should I do if its impossible to make a constant? thats my case: we have three variables, need to find that, one that will correspond to the value of the switch condition, but how to do this if the case is not able to work with non-constants? are there any workarounds?
float value = 4;
float number1 = 3, number2 = 6, number3 = 4;
switch (value)
{
case number1:
{
break;
}
case number2:
{
break;
}
case number3:
{
break;
}
}
here is the oversimplified example, and yes, you can easily do this using if/else if, but what if the number of values will be 100? what to do in that case?
One approach is to use an inverted Dictionary, where the key is the value and the value the key. Something like this:
var d = new Dictionary<int, int>();
d.Add(3, 1);
d.Add(6, 2);
d.Add(4, 3);
int keyPtr = d[value];
switch (keyPtr):
{
case 1:
//do something.
break;
case 2:
//do something else.
break;
case 3:
//do something different.
break;
}
Obviously this is simplified, and I have used int not float, but the same applies to any type. Using this technique,
your n variables, become the first n items in the Dictionary. In practice at the very least, you should check if your given value exists as a key in the Dictionary. It should help you in the right direction.
If you simply want to check whether your value variable equals to at least one of the variables number1, number2, number3, you could create an array of those numbers, say numbers[] and then create a method such as:
private bool checkValue(float value, float[] numbers) {
foreach (float num in numbers) {
if (num == value) return true;
}
return false;
}
This solution fits any number of elements in your numbers array.
If you want you can also use a List<float> instead of an array, so you could dynamically add more and more elements (Without a fixed size).

C# How to use variables as property names in an object List object constructor for key-value string arrays

Background:
I have parsed key-value pairs that I imported into objects. I did this because I want to be able to sort by the name properties which the logic is easy for:
var varDupe = variableList.GroupBy(v => v.varName).Where(vName => vName.Count() > 1).Select(vName => vName.Key);
I debated between these and a dictionary list, but in the end it seemed like searching was easier as I don't need to export these key-value pairs, only error-check them. I will need a lot of dependencies like "properties X,Y, and Z is required if property Q exists" for a few of my object lists and search through all of the distinct objects at once. If I would be better of with a list of dictionaries, please let me know.
My code works perfectly now with correctly sequenced key-value pairs, but as key value pairs, they inherently don't need to be grouped in the correct order. I made a sorting function for my parsed key-value string arrays
Issue
That function sorts the string arrays, but the problem comes when I have missing keys (for example, if varVal is optional). varVal and varParam should both be doubles, so I need to convert them in the object
Assume I have the string array leaving out an optional parameter.
varName,name1,varParam,1.01
The "full" array would look like this:
varName,name1,varVal,3.9,varParam,1.01
I have this code for building my objects:
switch (sortedVals.Count())
{
case 2:
materialList.Add(new Variable(sortedVals[1]));
break;
// Example of what I am trying to do to use the key-values to identify the correct property to assign a value to
case 4:
materialList.Add(new Variable(sortedVals[1]) { sortedVals[2] = Convert.ToDouble(sortedVals[3]) } );
break;
// Example of how it works correctly if they are all in order
case 6:
materialList.Add(new Variable(sortedVals[1], Convert.ToDouble(sortedVals[3]), Convert.ToDouble(sortedVals[5]) ) );
break;
...
If you look at "case 4" I am trying to use the "key" from string array to assign the correct "value" to. My Variable constructor inside my Variable class looks like this:
public Variable(string varName, double varVal = 1, double varParam = 0)
and
sortedVals[2] = "varParam"
The compiler doesn't recognize that my variable is intended to be used as a string for the constructor name (i.e. varParam = Convert.ToDouble("1.01") in case 4).
How can I use a string variable like this as a property name in a constructor?
Would I be better off scrapping the objects and trying to make a dictionary list and finding a way to search for name duplicates and other properties?
Thanks everyone!
There are different ways to achieve this:
This is a very basic solution, no linq etc. and assuming your split is always representing a single object:
string name;
double val = 1;
double val2 = 0;
for (int i = 0; i < sortedVals.length; i++)
{
string key = sortedVals[i];
i++;
string valString = sortedVals.length > i ? sortedVals[i] : string.Empty;
switch (key)
{
case "varName":
name = valString;
break;
case "varVal":
val = valString != string.Empty ? double.Parse(valString) : val;
break;
case "varParam":
val2 = valString != string.Empty ? double.Parse(valString) : val2;
break;
}
}
materialList.Add(new Variable(name, val, val2));

Sorting INT variables C#

I am just beginning with programming in c#;
I got a list of int variables that I want to sort, and find the number 1.
int Weapon_Count1, Weapon_Count2, Weapon_Count3, Weapon_Count4, Weapon_Count5, Weapon_Count6, Weapon_Count7, Weapon_Count8, Weapon_Count9
do I need to do this with an array?
By using the yellow book of C# I found out how to make an array, but I can't figure out how to assign the variables to the array.
int [] Weapon_Count = new int [11] ;
for ( int i=0; i<11; i=i+1)
{
Weapon_Count [i] = ??? ;}
I hope this does make sense..
Please let me explain how to use a C#-array.
This creates an unitialized integer-array with 5 elements:
int[] a1= new int[5];
Assigning values 9,8,7,6 and 5:
(Please note that only indexes from 0 to 4 can be used. Index 5 is not valid.)
a1[0]=9;
a1[1]=8;
a1[2]=7;
a1[3]=6;
a1[4]=5;
The same can also achieved with just one line:
int[] a1= new int[] {9,8,7,6,5};
This might help you.
// Declaring the array
int[] Weapon_Count;
// Initializing the array with a size of 11
Weapon_Count = new int[11];
// Adding values to the array
for (int i = 0; i < Weapon_Count.Length; i++)
{
Weapon_Count[i] = i + 100;
}
// Printing the values in the array
for (int i = 0; i < Weapon_Count.Length; i++)
{
Console.WriteLine(Weapon_Count[i]);
}
// Same thing with a list
// Daclare and initializing the List of integers
List<int> weapon_list = new List<int>();
// Adding some values
weapon_list.Add(1);
weapon_list.Add(2);
weapon_list.Add(3);
weapon_list.Add(4);
weapon_list.Add(5);
// Printing weapin_list's values
for (int i = 0; i < weapon_list.Count; i++)
{
Console.WriteLine(weapon_list[i]);
}
// This is just for the console to wait when you are in debug mode.
Console.ReadKey();
Dont forget to include the using statment if you want to use lists (in short hand - dynamic arrays that can change in size.)
using System.Collections.Generic;
The easiest way to do this, assuming there is a finite list of variables to check, would be to throw them into a temporary array and call either Max() or Min() from the System.Linq namespace.
int maxCount = new int[] { Weapon_Count1, Weapon_Count2, Weapon_Count3, Weapon_Count4, Weapon_Count5, Weapon_Count6, Weapon_Count7, Weapon_Count8, Weapon_Count9 }.Max(); // or .Min()
EDIT
If you still want to get those variables into an array, I would recommend using a System.Collections.Generic.List which has a dynamic size and helper methods such as .Add() to simplify things. Lists can also be used with Linq functions similar to the first part of my answer. See Dot Net Perls for some really good examples on different C# data types and functions.
EDIT 2
As #kblok says, you'll want to add using System.Linq; at the top of your file to gain access to the functions such as Max and Min. If you want to try using the List type, you'll need to add using System.Collections.Generic; as well. If you're in Visual Studio 2017 (maybe 2015 as well?) you can type out the data type and then hit Ctrl + . to get suggestions for namespaces that might contain that data type.
Before we start, you might edit your array to look like this:
int[] weapons = { Weapon_Count1, Weapon_Count2, Weapon_Count3, Weapon_Count4, Weapon_Count5, Weapon_Count6, Weapon_Count7, Weapon_Count8, Weapon_Count9 };
This means that you've created an array called weapons and it is holding integer values.
After you did this, lets find out which element in your array has value of number one.
To find which value has value "1" we must look at each element in array, and we might do that on few ways but I would like recommend foreach or for loop, in this case I will choose foreach loop.
foreach(var item in weapons)
{
if (item == 1)
//Do something
}
This above means, loop throught all of my elements, and in case some of them is equal to number one please do something..
P.S
(I may advice to create one variable which will hold an element which has value '1' and when you find it in a loop assing that variable to that element, and later you can do whatever you want with that variable.. and if you think there will be more elements with value of number one and you need all of them, instead of variable I mentioned above you will create list or array to hold all of your elements and also you can do later with them whatever you want to.)
Thanks and if you are interested in this kind of solution, leave me a comment so let me help you till the end to solve this if you are still struggling.

Assign a formula at runtime for accessing elements of List

The scenario is that I have say two different types of cases - case 1 and case 2. For case 1 and case 2 each I have a certain startIndex, endIndex and a formula for accessing the elements of a List.
Now for assigning values startIndex and endIndex I am preferring a normal switch case, however I am at loss for the formula for accessing elements. For case 1 it is say something like List[ a+i ] and for case 2 it is say List[a + (i-b)].
One way can be to have a for loop like this
for(int i=0;;i++)
{
if(case is 1)
then f=a+i
else if(case 2)
then f=a+(i-b)
}
I thought of using delegates. however, as per my knowledge they need to be made global. Actions do not return value. Func can be used but one expression/formula takes only one element (int) and the other takes 3. I need something in lines to this like that anonymous function can be assigned any of above mentioned formulae at runtime from the switch case (as the cases might and will increase in future).
Thank you.
I thought of using delegates. however, as per my knowledge they need
to be made global.
This is not true (actually, there are no truly global variables in C#, since each and every variable needs to be encapsulated inside an object). A public delegate type is indeed visible to all code after referencing the assembly containing this type's code, but a variable of such type can be private.
What I recommend in your situation is to have some sort of mapping from case numbers to delegates. A good idea is to use a Dictionary<TKey, TValue> if you have at most one delegate per case. This dictionary can be stored as a private variable inside the class where your method resides.
public class MyClass
{
private Dictionary<int, Delegate> _delegateMapping = new Dictionary<int, Delegate>;
}
There are a couple of ways you can add elements do the dictionary in the constructor: passing the already populated dictionary, passing an array of delegates, creating these delegates in the constructor itself. Either way, you'll end up with a dictionary of Delegate types, so you'll need to use a cast to be able to use them in your code properly.
for (int i = 1; i < _delegateMapping.Count; i++)
{
switch (i)
{
case 1:
var f = (Action<int>)_delegateMapping[1];
f(i);
break;
case 2:
var f = (Action<int, int>)_delegateMapping[2];
f(i, a);
break;
}
}
Of course I'm greatly improvising here.
It is important to note that if the type of delegate changes inside the dictionary, you will have to modify the cast accordingly inside the switch statement. Otherwise, if no implicit cast exists, you'll get a runtime exception.
Hi guys thank you so very much for your feedbacks. I finally found the solution with Func. This is what my code looks like. I had to manipulate the Func usage a little. I made almost all the vars which I have to use in the Func as global/local to the function where I write these Funcs. My apologies, if I was not able to explain my problem properly.
int i = -1;
Func<int,int> formula = null;
switch(f)
{
case 1:
{
formula = new Func<int,int>(index => { return i; });
}
break;
case 2:
{
formula = new Func<int, int>( index => { return s- (i * c); } );//here s and c are global variables.
}
break;
}
i = startIndex;
while(i < endIndex)
{
var Obj= List[formula.Invoke(i)];
//my code goes here
i++;
}
Let me know if my solution is correct w.r.t performance, logic, C# programming, etc.. :)
EDITED::
#usr and #Kapol I tried the way you suggested and tried to improvise the code like this.
private Dictionary<int, Func<int[], int>> indexFormulae;
private void assignDelegates()
{
indexFormulae = new Dictionary<int, Func<int[], int>>();
indexFormulae.Add(0, getFormula_1);
indexFormulae.Add(1, getFormula_2);
}
private void someFunction(int sp)
{
int i = 0;
Func<int[], int> formula = null;
indexFormulae.TryGetValue(formation,out formula);
i = startIndex;
while (i < endIndex)
{
int[] intValues = new int[] {i,sp,globalVar };
var Obj = List[formula.Invoke(intValues)];
//My code here
i++;
}
}
private int getFormula_1(params int[] intValues)
{
return intValues[0];
}
private int getIndex_Vertical(params int[] intValues)
{
return intValues[1] - (intValues[0] * intValues[2]);
}
So, that with this now I can use these two getFormula methods anywhere in this class rather than keeping them anonymous. and also I think I will stick to params because I might have N number of int params in future for other functions.

"a constant value is expected" error in switch statement in c#

switch (Rotation.ToString())
{
case (-Math.PI / 2).ToString():
// some code
break;
}
The compiler complains about (-Math.PI / 2).ToString(), "a constant value is expected"
Isn't that a constant?
No method call is a constant value.
Incidentally, since Math.PI is a double, you might want to not use it in "equality" comparisons as you are doing here; there are well-documented pitfalls.
A better approach for a single test would be:
var target = -Math.PI / 2;
if (Math.Abs(Rotation - target) < 0.0001) {
// some code
}
If there are lots of branches, without going into delegate territory, you can do something like this:
var specialCases = new[] { -Math.PI, -Math.PI / 2 };
var epsilon = 0.001d;
var index = specialCases.Select((d, i) => Math.Abs(Rotation - d) < epsilon ? i : -1)
.Where(i => i != -1).DefaultIfEmpty(-1).First();
switch (index) {
case 0: // -Math.PI
break;
case 1: // -Math.PI / 2
break;
default: // No match
break;
}
Not the best use of LINQ, but it will allow you to get back to switch territory with a minimum of tinkering.
Jon answers the gist of the question: the result of a method call is never considered to be a constant from the compiler's perspective. You can do this:
string i = (-Math.PI / 2).ToString();
switch(i)
{
case "-1.5707963267949": Console.WriteLine("hi");
break;
}
However, bear in mind that double.ToString() may produce different results depending on the current culture info. (Hence the reason it cannot be constant.) So you're probably better off using the double value directly and, depending on the size of your switch statement, either creating a few if/else statements, or creating a Dictionary keyed on the constant value you're trying to match.
And of course, Jon's initial warning still holds true: while doing floating-point logic, you could very easily end up with a value that should be -pi/2, but which isn't exactly -pi/2, in which case your check will fail. Here be dragons.
Perhaps try:
const var SomeVar = (-Math.PI / 2).ToString();
switch (Rotation.ToString())
{
case SomeVar:
// some code
break;
}

Categories