Address custom enum values by order - c#

Usually I can address each item in an enum by it's ordered position (0, 1, 2, 3...), but if I've created an enum with custom values (as below), is there still a way to address each item by its declared order (e.g., Off = 0, _5m = 1, _15m = 2, etc.), rather than its value?
enum WaitTime { Off = 0, _5m = 5, _15m = 15, _30m = 30, _1h = 60, _2h = 120, _3h = 180, _6h = 360, _12h = 720, _1d = 1440, _2d = 2880 }

In C# You can use Enum.GetValues() method.
It retrieves an array of the values of the constants in a specified
enumeration. The elements of the array are sorted by the binary values
of the enumeration constants.
Array enumElementsInArray = Enum.GetValues(typeof(WaitTime));
int firstElement = enumElementsInArray[0];
int secondElement = enumElementsInArray[1];
But know that, it will return the aray after sorting elements by their values. But of course, for your enum it will work as you want.

This would be a generic way that works for all types of enums:
public static T GetValueAt<T>(int idx)
{
var vals = Enum.GetValues(typeof(T));
return (T)vals.GetValue(idx);
}
Usage:
var value = GetValueAt<WaitTime>(2); //returns _15m

(Answer for C#)
No you wont, e.g. _5m converts to 5, not to 1.
What you call "order" is an implicit conversion to an integer (which by default is 0 ... N-1 for an enum with N values)
enum WaitTime { Off = 0, _5m = 5, _15m = 15, _30m = 30, _1h = 60, _2h = 120, _3h = 180, _6h = 360, _12h = 720, _1d = 1440, _2d = 2880 }
class Program
{
static void Main()
{
WaitTime wt = WaitTime._15m;
Console.WriteLine((int)wt);
}
}
Will output 15.
PS.: avoid leading underscores when declaring your enum values.

Related

How to sort an array of strings of zeros and ones?

I am trying to sort an array of ints by it's binary form. for example if i have {1,2,3} i must convert them to binary then sort them based on how many 1 each has, if the number only has one 1 then it is number 1 and then comes the number that has two 1s in its binary form and so on.
i tried to use the following two methods but i couldn't do them due to errors and i don't understand. i searched all stackoverflow but can't figure it out, i am stuck for our here in this problem.
public static int[] xx = { 1, 2, 3, 4, 5, 6, 87, 8, 9, 7, 5, 24, 58, 63, 10, 11, 87, 20, 22, 90, 14, 17, 19, 21, 18, 24 };
public string[] ChangeToBinary(int[] data)
{
string[] binary = new string[data.Length];
var i = 0;
foreach (int d in data)
{
string newvalue = Convert.ToString(d, 2);
binary[i] = newvalue;
i++;
}
return binary;
}
public int[] Sort(string[] binaries)
{
Array.Sort(binaries, (x, y) => x.Count(z => z == '1') > y.Count(e => e == '1'));
string[] sorted = binaries.OrderBy(b => b.Count(z => z == '1') > b.Count(e => e == '1'));
}
the two lines inside the sort function i know that they are wrong in some point that i dont get can someone tell me how to do it ? i try to say to sort the elements of the array based on the least number of 1s in the element.
I won;t use both but i put them to show you what i wanted to use.
thanks in advance.
With a help of Convert and Linq you can easily count 1s:
int value = ...
ones = Convert
.ToString(value, 2) // Binary representation
.Count(c => c == '1'); // Count 1's
Having this done, let's sort the array:
int[] xx = ...
int[] sorted = xx
.OrderBy(value => Convert // criterium: see the code above
.ToString(value, 2)
.Count(c => c == '1'))
.ThenBy(value => value) // on tie e.g. 0b101 and 0b110 let's use value
.ToArray();
There are two different approaches to custom sorting:
You provide a comparison between any two elements. This is what Array.Sort takes. The comparison has to return an int with a value that's negative, zero or positive to indicate whether the first element is less than, equal to or greater than the second element. (Your lambda expression currently returns bool because you're using >.)
You provide a projection from one element, and the sort algorithm compares the results of that projection. That's what OrderBy does - but the lambda expression you're providing in the OrderBy compares the count of one element with the count from the same element.
I would suggest using the OrderBy approach, because that's much simpler. You're just trying to order by the count, so you just need to count the 1s in the element you're provided, and return that count:
string[] sorted = binaries.OrderBy(b => b.Count(z => z == '1')).ToArray();
Now your method is meant to return an int[] at the moment. Presumably it would convert each binary string back to an int. I'd suggest not doing that - instead change your Sort method to return the sorted string[]. You can then perform the conversion in another method, whether that's a separate method or the calling method.
That's the approach I'd take first, as the minimal change to your code - and as a way of understanding what's going on in the Sort and OrderBy methods. You can then potentially change to order the integers directly without ever directly creating an array of strings, as Dmitry suggests.
A solution for those of us who are just tip-toeing around Linq. More code but remember the linq is looping underneath.
public static int[] xx = { 1, 2, 3, 4, 5, 6, 87, 8, 9, 7, 5, 24, 58, 63, 10, 11, 87, 20, 22, 90, 14, 17, 19, 21, 18, 24 };
public class MyBinary
{
public string BinString { get; set; }
public int OneCount { get; set; }
public int OriginalInt { get; set; }
public MyBinary(string input, int count, int original)
{
OriginalInt = original;
BinString = input;
OneCount = count;
}
}
private List<MyBinary> SortByOnes(int[] input)
{
List<MyBinary> lst = new List<MyBinary>();
//The following will give a result First ordered by number of ones but also
// secondarily the original numbers
//just a bit of linq
int[] SortedArray = (from i in input orderby i select i).ToArray();
List <MyBinary> lstSorted = new List<MyBinary>();
int index = 0;
string[] Bin = new string[SortedArray.Count()];
foreach (int i in SortedArray)
{
Bin[index] = Convert.ToString(i, 2);
int oneCount = 0;
foreach (char c in Bin[index])
{
if (c == '1')
oneCount += 1;
}
//sends the binary string, the count of ones, and the original number
//to the constructor of MyBinary
lst.Add(new MyBinary(Bin[index], oneCount, i));
lstSorted = (from b in lst orderby b.OneCount descending select b).ToList();
index += 1;
}
return lstSorted;
}
//To use:
private void TestSort()
{
List<MyBinary> lst = SortByOnes(xx);
foreach (MyBinary b in lst)
{ Debug.Print($"{b.OneCount} - {b.BinString} - {b.OriginalInt}"); }
}

C# How to convert an enum to based Bin/Oct/Dec/Hex string and vice versa

I was looking for a generic way, representing any type of enum as a bin/oct/dec/hex-based string value.
Convert.ToType(Byte,SByte,Int16,UInt16,....) provides support, converting based string to desired type. But Convert.ToString, have just basement support for Type byte (unsigned), short(signed), int(signed), long(long). If you don't pay attantion you'll try getting bin-based string from UInt.Max:
Convert.ToString(UInt.MaxValue, 2) But there is no base support for UInt32, so 2 is intepreted as IFormatProvider.
Hex has a ToString Formatprovider, but it gives diffrent output than. Convert.ToString(,16).
Conver.ToString((short)79,16) // 4F
((short)79).ToString("X") // 4f
I'll make it quick, no consequent implementation, signed / unsigned problems, casting traps. While working with enum, you dont have an enum generic support. virieté of possible enumbase types and so on.
All what I would like, is representing any enum as based string and cast based string back to desired enum.
I'have put a little effort and created 2 Converters for that, Code implementation are available on following gist:
BasedEnumConverter and Helper: https://gist.github.com/chubbson/816b24a59e5f7e90385e
BasedValueConverter https://gist.github.com/chubbson/375b535243c166d28119
void Main()
{
var os = Tshort.Convesionfailed.ToStringOct().Dump(); //000120
BasedEnumConverter<Tshort>.ParseEnumFromOct(os).Dump(); //Conversionfailed
var stsbbin = Tsbyte.BAD.ToStringBin().Dump(); //10000000
BasedEnumConverter<Tsbyte>.ParseEnumFromBin(stsbbin).Dump(); //BAD
var sinthex = Tint.OK.ToStringHex().Dump(); //00000080
BasedEnumConverter<Tint>.ParseEnumFromHex(sinthex).Dump(); //OK
}
enum Tenum : byte { A = 0, B = 1, OK = 128, BAD = 255, Convesionfailed = 80 }
enum Tbyte : byte { A = 0, B = 1, OK = 128, BAD = 255, Convesionfailed = 80 }
enum Tsbyte : sbyte { A = 0, B = 1, OK = 127, OK2 = 126, BAD = -128, BAD2 = -127, Convesionfailed = 80 }
enum Tshort : short { A = 0, B = 1, OK = 128, BAD = 255, Convesionfailed = 80 }
enum Tushort : ushort { A = 0, B = 1, OK = 128, BAD = 255, Convesionfailed = 80 }
enum Tint : int { A = 0, B = 1, OK = 128, BAD = 255, Convesionfailed = 80 }
enum Tuint: uint { A = 0, B = 1, OK = 128, BAD = 255, Convesionfailed = 80 }
enum Tlong : long { A = 0, B = 1, OK = 128, BAD = 255, Convesionfailed = 80 }
enum Tulong : ulong { A = 0, B = 1, OK = 128, BAD = 255, Convesionfailed = 80, Min = ulong.MinValue, Max = ulong.MaxValue}
Please Review the code, give me a hint about performance/oop, what is conceptually wrong or could be done better. My first (or second approach was trying to calc the values by self with some shift and stringappending, but i discarted this cuz of 8 enum base types)

c# loop through all fields of enum assigning values from string array

I am building a Soap Body for a web-service, and there are dozens of optional fields.
Currently I have been handling these like this:
wsSoapBody.OrderType = aMessage[(int)cardCreate.OrderType].ToString();
wsSoapBody.ActivateFlag = Convert.ToInt32(aMessage[(int)cardCreate.ActivateFlag].ToString()); //P-02925;
if (aMessage[(int)cardCreate.ShipDate].ToString() != ""){
wsSoapBody.ShipmentDate = Convert.ToDateTime(aMessage[(int)cardCreate.ShipDate].ToString()); //P-02925;
}
wsSoapBody.ShipmentMethodCard = aMessage[(int)cardCreate.ShipMethodCard].ToString();
wsSoapBody.ShipmentMethodPin = aMessage[(int)cardCreate.ShipMethodPIN].ToString();
The CardCreate you see in those value assignments is an enumerated constant in the class cardCreate defined as below:
namespace EvryCardManagement
{
class CardCreate
{
#region Variables
private DCSSCardCreateType req;
private DCSSCardCreateResponseType rsp;
private DCSSCardCreate_V3_0Service stub;
public string tokenID { get; set; }
private enum cardCreate
{
MsgType = 0,
MsgVersion = 1,
WSName = 2,
ReplyTo = 3,
SourceSystem = 4,
Timestamp = 5,
UniqueMessageID = 6,
SFDCContext = 7,
InstitutionID = 8,
CardNumber = 9,
Version = 10,
ProductID = 11,
AccountNumber = 12,
CustomerID = 13,
CustomerNumber = 14,
EmbossName1 = 15,
Expiry = 16,
FeeMonth = 17,
ChargeAccountNo = 18,
PINMethod = 19,
CardFlag = 20,
AddressTypeCard = 21,
AddressTypePIN = 22,
OrderType = 23,
ActivateFlag = 24,
ShipDate = 25,
ShipMethodCard = 26,
ShipMethodPIN = 27,
FirstName = 28,
LastName = 29,
CardAddress1 = 30,
CardAddress2 = 31,
CardAddress3 = 32,
CardAddress4 = 33,
CardAddress5 = 34,
CardAddress6 = 35,
CardPostCode = 36,
CardCity = 37,
CardCountry = 38,
PINName = 39,
PINAddress1 = 40,
PINAddress2 = 41,
PINAddress3 = 42,
PINAddress4 = 43,
PINAddress5 = 44,
PINAddress6 = 45,
PINPostCode = 46,
PINCity = 47,
PINCountry = 48,
Validfrom = 49,
Note = 50,
MakeCheckStatus = 51,
EmbossName2 = 52,
PAmount = 53,
PAmountLength = 54,
GKIndicator = 55,
CreditLimit = 56,
CardDesignNo = 57,
ExtPictureID = 58,
BulkID = 59,
AccountNo2 = 60
}
so, rather than doing them all one by one as I have been doing, is it possible to loop through the wsSoapBody (which is defined in the web-service) and for each one, get the corresponding value from the aMessage (which is defined as an array like this string[] aMessage)
EDIT
I have the below code to loop through, but I want to assign to the wsSoapBody and I am stuck:
foreach (cardCreate cItem in (cardCreate[])Enum.GetValues(typeof(cardCreate)))
{
}
(the above correction was suggested as an edit by Steve Lillis that was rejected due to a conflict)
so I don't know how then to assign the values to each element for example I want to set
wsSoapBody[cItem].value = aMessage[(int)CardCreate[cItem]`
or I also tried:
wsSoapBody[cItem] = aMessage[(int)cItem].ToString();
but am having trouble making it work (or even compile) due to lack of knowledge
EDIT #2:
I have also looked at GetNames as possibly I want the names and tried:
foreach (string name in Enum.GetNames(typeof(cardCreate)))
{
wsSoapBody[name] = aMessage[(int)name].ToString();
}
But I cannot apply indexing with [] to an expression of type 'DCSSCardCreateType'
thanks
Why not place the values onto the enum itself and then enumerate?
For example using System.ComponentModel Description attribute we can add that information to the enum itself such as:
public enum cardCreate
{
[Description("General Response")]
MsgType = 0,
[Description("V2.0")]
WSName = 2,
[Description("OmegaMan")]
ReplyTo = 3,
[Description("Windows 10")]
SourceSystem = 4,
}
So when we call a special method to enumerate the enum where we can extract that text and use it appropriately later such as:
myextensions.GetEnumValues<cardCreate>()
.Select (ceEnum => new
{
Original = ceEnum,
IndexValue = (int)ceEnum,
Text = ceEnum.GetAttributeDescription()
})
The dynamic entity will look like this after the projection (the select):
Sweet! Now we have all the information in a easy consumable entity which provides all the information needed.
What? You need more than a string description? Then create a custom attribute on the enum and have all items/types of data to return as needed. For that see my blog article C# Using Extended Attribute Information on Objects.
Here are the extension methods used in the above example:
public static class myextensions
{
public static IEnumerable<T> GetEnumValues<T>()
{
Type type = typeof( T );
if (!type.IsEnum)
throw new Exception( string.Format("{0} is not an enum.", type.FullName ));
FieldInfo[] fields =
type.GetFields( BindingFlags.Public | BindingFlags.Static );
foreach (var item in fields)
yield return (T)item.GetValue( null );
}
/// <summary>If an attribute on an enumeration exists, this will return that
/// information</summary>
/// <param name="value">The object which has the attribute.</param>
/// <returns>The description string of the attribute or string.empty</returns>
public static string GetAttributeDescription( this object value )
{
string retVal = string.Empty;
try
{
retVal = value.GetType()
.GetField( value.ToString() )
.GetCustomAttributes( typeof( DescriptionAttribute ), false )
.OfType<DescriptionAttribute>()
.First()
.Description;
}
catch (NullReferenceException)
{
//Occurs when we attempt to get description of an enum value that does not exist
}
finally
{
if (string.IsNullOrEmpty( retVal ))
retVal = "Unknown";
}
return retVal;
}
}

Linear Algebra MatrixMultiply method

EDIT:
After fixing the syntax error and working with this algorithm I found the MKL provider is not the matrix multiplication needed. This algorithm simply multiplies element by element and does not compute the dot(row_n,column_n) as I had originally thought.
other source
End Edit
I can't get this passed the compiler. I have looked all over for a good example but have come up short. The documentation I'm referencing is MklLinearAlgebraProvider
MathNet.Numerics.Algorithms.LinearAlgebra.Mkl.MklLinearAlgebraProvider
I'm trying to write a simple method to compute the rotation matrix R = rz*ry*rx from Euler angles. The problem is the compiler won't take ryXrx or resultMat arrays I'm trying to pass it. I've tried out keyword as well.
inputMat is a 1-D array of the form {x,y,z,rx,ry,rz} where x,y and z are translations and rx,ry and rz are rotation angles in degrees.
private float[,] EulerToHMat(float[] inputMat)
{
var linalg = new MathNet.Numerics.Algorithms.LinearAlgebra.Mkl.MklLinearAlgebraProvider();
double rzRad = ((double)inputMat[5])*Math.PI/180;
double cosZ = Math.Cos(rzRad);
double sinZ = Math.Sin(rzRad);
double ryRad = ((double)inputMat[4])*Math.PI/180;
double cosY= Math.Cos(ryRad);
double sinY = Math.Sin(ryRad);
double rxRad = ((double)inputMat[3])*Math.PI/180;
double cosX= Math.Cos(rxRad);
double sinX = Math.Sin(rxRad);
var rz = new float[,] { { (float)cosZ, -(float)sinZ, 0 }, { (float)sinZ, (float)cosZ , 0 }, {0,0,1 } };
var ry = new float[,] { { (float)cosY , 0 , (float)sinY }, { 0, 1 , 0 }, { -(float)sinY, 0, (float)cosY } };
var rx = new float[,] { {1,0,0 }, {0,(float)cosX,-(float)sinX }, {0,(float)sinX,(float)cosX } };
var ryXrx = new float[3,3];
var resultMat = new float[3, 3];
// won't take the matrix --ryXrx-- here
linalg.MatrixMultiply(ry, 3, 3, rx, 3, 3,ryXrx);
// won't take the matrix --resultMat-- here
linalg.MatrixMultiply(rz, 3, 3, ryXrx, 3, 3,resultMat);
return resultMat;
}
This seems like it should be simple.... Please ignore the casting mess.
According to the reference you linked, the method works on matrices that are stored in a SINGLE-dimensional array, you are trying to pass two-dimensionals.
Try this:
var rz = new float[] { (float)cosZ, -(float)sinZ, 0, (float)sinZ, (float)cosZ, 0, 0, 0, 1 };
var ry = new float[] { (float)cosY, 0, (float)sinY, 0, 1, 0, -(float)sinY, 0, (float)cosY };
var rx = new float[] { 1, 0, 0, 0, (float)cosX, -(float)sinX, 0, (float)sinX, (float)cosX };
int size = 3;
var ryXrx = new float[size * size];
var resultMat = new float[size * size];
// won't take the matrix --ryXrx-- here
linalg.MatrixMultiply(ry, size, size, rx, size, size,ryXrx);

Mapping Vectors

Is there a good way to map vectors? Here's an example of what I mean:
vec0 = [0,0,0,0,0,0,0,0,0,0,0]
vec1 = [1,4,2,7,3,2]
vec2 = [0,0,0,0,0,0,0,0,0]
vec2 = [7,2,7,9,9,6,1,0,4]
vec4 = [0,0,0,0,0,0]
mainvec =
[0,0,0,0,0,0,0,0,0,0,0,1,4,2,7,3,2,0,0,0,0,0,0,0,0,0,7,2,7,9,9,6,1,0,4,0,0,0,0,0,0]
Lets say mainvec doesn't exist (I'm just showing it to you so you can see the general data structure in mind.
Now say I want mainvec(12) which would be 4. Is there a good way to map the call of these vectors without just stitching them together into a mainvec? I realize I could make a bunch of if statements that test the index of mainvec and I can then offset each call depending on where the call is within one of the vectors, so for instance:
mainvec(12) = vec1(1)
which I could do by:
mainvec(index)
if (index >=13)
vect1(index-11);
I wonder if there's a concise way of doing this without if statements. Any Ideas?
Are you looking for something like this?
using System.Collections.Generic;
namespace Test
{
class Program
{
static void Main(string[] args)
{
int[] vec0 = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
int[] vec1 = { 1, 4, 2, 7, 3, 2 };
int[] vec2 = { 0, 0, 0, 0, 0, 0, 0, 0, 0 };
int[] vec3 = { 7, 2, 7, 9, 9, 6, 1, 0, 4 };
int[] vec4 = { 0, 0, 0, 0, 0, 0 };
List<int> temp = new List<int>();
temp.AddRange(vec0);
temp.AddRange(vec1);
temp.AddRange(vec2);
temp.AddRange(vec3);
temp.AddRange(vec4);
int[] mainvec = temp.ToArray();
}
}
}
I would create a class that would receive array of lengths, and have a method to give you Array number and Index inside the array for a given index in the combined list.
It would be wrapped by a class that will get references to the actual arrays and an indexer to bring you to the right element.
It looks like your doing basic list concatenation, in which case the Concat function would seem to be the most straight forward way of doing things. In real-live code terms, somethng like:
var vec0 = new[] {0,0,0,0,0,0,0,0,0,0,0};
var vec1 = new[] {1,4,2,7,3,2};
var vec2 = new[] {0,0,0,0,0,0,0,0,0};
var vec3 = new[] {7,2,7,9,9,6,1,0,4};
var vec4 = new[] { 0, 0, 0, 0, 0, 0 };
var mainvec = vec0.Concat(vec1).Concat(vec2).Concat(vec3).Concat(vec4).ToList();
mainvec[12] == 1;
I'm not really sure of the context behind what you are wanting to do, so there may be a more direct way of doing things, but based on what you've got, this seems the simplest to me.
I would use a jagged array.
You still have to have a loop, but you can keep the separate vectors without redundancy:
var mainvec = new int[][]{vec0, vec1, vec2, vec3, vec4};
int desiredInd = 12, totalInd = 0, rowInd = 0, result;
while(rowInd < mainvec.Length && (totalInd + mainvec[rowInd].Length) <= desiredInd)
{
totalInd += mainvec[rowInd++].Length;
}
if(rowInd < mainvec.Length && (desiredInd - totalInd) < mainvec[rowInd].Length)
{
result = mainvec[rowInd][desiredInd - totalInd];
}

Categories

Resources