I have a list of Enums like the following:
public enum Evaluation : int
{
//Section 1
S1_1_1 = 579,
S1_1_2 = 584,
S1_1_3 = 589,
S1_1_4 = 594,
S1_1_5 = 599,
S1_1_6 = 604,
//Section 2
S1_2_1 = 610,
S1_2_2 = 615,
S1_2_3 = 620,
S1_2_4 = 625,
S1_2_5 = 630,
};
I want to iterate each section and use the values dynamically
int S1Count = 6;
for (int i = 1; i <= S1Count; i++)
{
VoteCount += string.IsNullOrEmpty(this.GetEvaluationValue(FormID, Evaluation.S1_1_ + i)) ? 0 : 1;
}
How can I achieve that? Thanks.
Sorry, my mistake. I tried to get the value from the database by using enum values which are IDs and I have to calculate counts, average for each section.
You can use Enum.Parse to do what you want I think though I don't reccomend it.
To use enum.Parse you'd just need to do something like:
Enum.Parse(typeof(Evaluation), String.Format("S1_1_{0}",i));
This does point at you using some dodgy methodology though. As I said in comments above you would be better off with a data structure allowing you to have sections and their contents easily differentiated. You can do this with either custom classes or maybe just a dictionary of Lists of ints...
Dictionary<int, List<int>> SectionContents;
and use it like:
foreach(int id in SectionContents[sectionNumber])
{
VoteCount += string.IsNullOrEmpty(this.GetEvaluationValue(FormID, id)) ? 0 : 1;
}
(I don't vouch for what's in the foreach, I'm just demonstrating how a dictionary of a list of ints could work).
Creating the Dictionary is easy enough and doesn't require enums. And if this is database stuff could easily be generated through a database query to get the IDs and what sections they are in and then create the data structure.
This will do it
public class Program
{
public static void Main()
{
foreach (FieldInfo fInfo in typeof(Evaluation).GetFields(BindingFlags.Public | BindingFlags.Static))
{
Console.WriteLine("Evaluation." + fInfo.Name);
}
Console.ReadLine();
}
}
Related
So I have a enumflag system and I need to filter by Narcotic, non-Narcotic, Psychotropic, and non-Psychotropic in a drop down list. My thinking was to put the values in dictionary and they viewbag into a selectlist on the front end, but I am having trouble configuring the dictionary to register "the absense of [var]"
If my dictionary is structured as thus:
private readonly Dictionary<int, string> _medicationDetails = new Dictionary<int, string>
{
{(int)PersonMedicationDescription.MedicationTags.NarcoticDrug, "Narcotic"},
{(int)PersonMedicationDescription.MedicationTags.PsychotropicDrug, "Psychotropic"}
};
I want to be able to do:
{(int)!PersonMedicationDescription.MedicationTags.NarcoticDrug, "non-Narcotic"},
or something along those lines. What am I missing here? Is there a better way to accomplish this?
EDIT:
Is a bool the right way to go. I know how to do that if it were just one bool, but how do I get both to populate the list? To get one to work I think this would work:
ViewBag.IsNarcoticOptions = new[]
{
true,
false
}.ToSelectList(b => b.ToString(), b => b.ToString("Narcotic", "Non Narcotic"));
var isNarcotic = filters.IsNarcotic;
if (isNarcotic.HasValue)
{
query = isNarcotic.Value
? query.Where(rdq => (rdq.MedicationFlags & (int)PersonMedicationDescription.MedicationTags.NarcoticDrug) == (int)PersonMedicationDescription.MedicationTags.NarcoticDrug)
: query.Where(rdq => (rdq.MedicationFlags & (int)PersonMedicationDescription.MedicationTags.NarcoticDrug) == 0);
}
but how to do that for another set of true/false?
It seems that you are dealing with flags: a drug is either Narcotic or not, either Psychotropic; flags can be combined:
we can well have Narcotic and Psychotropic (LSD?) or neither Psychotropic nor Narcotic (Aspirin). If you have few flags (less than 64) you can try designing the enum as Flags and get rid of dictionary
[Flags]
public enum MedicationTags {
None = 0,
Narcotic = 1,
Psychotropic = 1 << 1,
// SomeOtherKind = 1 << n // where n = 2, 3, 4 etc.
}
Then let's implement an extension method Description for the enum:
public static class MedicationTagsExtensions {
public static String Description(this MedicationTags value) {
return string.Join(", ",
(value.HasFlag(MedicationTags.Narcotic) ? "" : "non-") + "Narcotic",
(value.HasFlag(MedicationTags.Psychotropic) ? "" : "non-") + "Psychotropic"
);
}
}
So when having drug kind:
// Morphine is narcotic only
MedicationTags morphine = MedicationTags.Narcotic;
// LSD is both narcotic and psychotropic
MedicationTags lsd = MedicationTags.Narcotic | MedicationTags.Psychotropic;
// Good old aspirin is neither narcotic nor psychotropic
MedicationTags aspirin = MedicationTags.None;
you can easily get description
Console.WriteLine(aspirin.Description());
Outcome:
non-Narcotic, non-Psychotropic
Is there a way of creating a table with each cell containing a string in C# ?
The closest thing I found is multidimensional arrays string[,] names;, but it seems like its length needs to be defined which is a problem to me.
Here is what my code looks like :
string[] namePost;
int[] numbPage;
string post="";
string newPost;
int i=0;
int j=0;
foreach (var line in File.ReadLines(path).Where(line => regex1.Match(line).Success))
{
newPost = regex1.Match(line).Groups[1].Value;
if (String.Compare(newPost, post) == 0)
{
j = j + 1;
}
else
{
namePost[i] = post;
numbPage[i] = j;
post = newPost;
j = 1;
i = i + 1;
}
}
Each instance of the for writes the name of the new "post" in a cell of namePost. In the end, the namePost table stores the name of all the posts that are different from one another.
What is the best way to achieve that ?
If you are simply trying to store the posts, you can use the List class from the System.Collections.Generic namespace:
using System.Collections.Generic;
List<String> namePost = new List<String>();
Then, instead of namePost[i] = post;, use
namePost.Add(post);
DataTable
https://msdn.microsoft.com/en-us/library/system.data.datatable(v=vs.110).aspx
Use this, no need to define length at all.
Useful guide and examples:
http://www.dotnetperls.com/datatable
You can just use a
var table = new List<List<string>>();
This would give you a dynamic 2D table of strings.
This will give you all your unique posts. If you want the result as a list you can just do a
.ToList ()
with the result.
static IEnumerable<string> AllPosts(Regex regex, string filePath)
{
return File.ReadLines (filePath)
.Where (line => regex.Match (line).Success)
.Select (line => regex.Match (line).Groups [1].Value)
.Distinct ();
}
At the moment I'm adding functionality to our service that will take in an object that is about to be logged to trace and mask any sensitive fields that are included in the object.
The issue is that we can get objects with different layers. The code I have written so far only handles a parent field and a single child field and uses a nasty embedded for loop implementation to do it.
In the event that we have a third embedded layer of fields in an object we want to log, this wouldn't be able to handle it at all. There has to be a more efficient way of handling generic parsing of a dynamic object, but so far it's managed to avoid me.
The actual code that deserializes and then masks field sin the object looks like this:
private string MaskSensitiveData(string message)
{
var maskedMessage = JsonConvert.DeserializeObject<dynamic>(message);
LoggingProperties.GetSensitiveFields();
for (int i = 0; i < LoggingProperties.Fields.Count(); i++)
{
for (int j = 0; j < LoggingProperties.SubFields.Count(); j++)
{
if (maskedMessage[LoggingProperties.Fields[i]] != null)
{
if (maskedMessage[LoggingProperties.Fields[i]][LoggingProperties.SubFields[j]] != null)
{
maskedMessage[LoggingProperties.Fields[i]][LoggingProperties.SubFields[j]] = MaskField(LoggingProperties.SubFieldLengths[j]);
}
}
}
}
return maskedMessage.ToString(Formatting.None);
}
And it works off of a LoggingProperties class that looks like this:
public static class LoggingProperties
{
// Constants indicating the number of fields we need to mask at present
private const int ParentFieldCount = 2;
private const int SubFieldCount = 4;
// Constant representing the character we are using for masking
public const char MaskCharacter = '*';
// Parent fields array
public static string[] Fields = new string[ParentFieldCount];
// Subfields array
public static string[] SubFields = new string[SubFieldCount];
// Array of field lengths, each index matching the subfield array elements
public static int[] SubFieldLengths = new int[SubFieldCount];
public static void GetSensitiveFields()
{
// Sensitive parent fields
Fields[0] = "Parent1";
Fields[1] = "Parent2";
// Sensitive subfields
SubFields[0] = "Child1";
SubFields[1] = "Child2";
SubFields[2] = "Child3";
SubFields[3] = "Child4";
// Lengths of sensitive subfields
SubFieldLengths[0] = 16;
SubFieldLengths[1] = 16;
SubFieldLengths[2] = 20;
SubFieldLengths[3] = 3;
}
}
}
The aim was to have a specific list of fields for the masking method to look out for that could be expanded or contracted along with our systems needs.
The nested loop method though just seems a bit roundabout to me. Any help is appreciated.
Thanks!
UPDATE:
Here's a small example of a parent and child record that would be in the message prior to the deserialize call. For this example say I'm attempting to mask the currency ID (So in properties the fields could be set like this: Parent1 = "Amounts" and Child1 = "CurrencyId"):
{
"Amounts":
{
"Amount":20.0,
"CurrencyId":826
}
}
An example of a problem would then be if the Amount was divided into pounds and pence:
{
"Amounts":
{
"Amount":
{
"Pounds":20,
"Pence":0
},
"CurrencyId":826
}
}
This would another layer and yet another embedded for loop...but with that I would be making it overly complex and difficult if the next record in a message had only two layers.
Hope this clarifies a few things =]
Okay, I've really tried but I couldn't figure out an elegant way. Here's what I did:
The first try was using reflection but since all the objects are of type JObject / JToken, I found no way of deciding whether a property is an object or a value.
The second try was (and still is, if you can figure out a good way) more promising: parsing the JSON string into a JObject with var data = JObject.Parse(message) and enumerating its properties in a recursive method like this:
void Mask(data)
{
foreach (JToken token in data)
{
if (token.Type == JTokenType.Object)
{
// It's an object, mask its children
Mask(token.Children());
}
else
{
// Somehow mask it but I couldn't figure out to do it with JToken
// Pseudocode, it doesn't actually work:
if (keysToMask.Contains(token.Name))
token.Value = "***";
}
}
}
Since it doesn't work with JTokens, I've tried the same with JProperties and it works for the root object, but there's a problem: although you can see if a given JProperty is an object, you can not select its children object, JProperty.Children() gives JToken again and I found no way to convert it to a JProperty. If anyone knows how to achieve it, please post it.
So the only way I found is a very dirty one: using regular expressions. It's all but elegant - but it works.
// Make sure the JSON is well formatted
string formattedJson = JObject.Parse(message).ToString();
// Define the keys of the values to be masked
string[] maskedKeys = {"mask1", "mask2"};
// Loop through each key
foreach (var key in maskedKeys)
{
string original_pattern = string.Format("(\"{0}\": )(\"?[^,\\r\\n]+\"?)", key);
string masked_pattern = "$1\"censored\"";
Regex pattern = new Regex(original_pattern);
formatted_json = pattern.Replace(formatted_json, masked_pattern);
}
// Parse the masked string
var maskedMessage = JsonConvert.DeserializeObject<dynamic>(formatted_json);
Assuming this is your input:
{
"val1" : "value1",
"val2" : "value2",
"mask1" : "to be masked",
"prop1" : {
"val3" : "value3",
"val1" : "value1",
"mask2" : "to be masked too",
"prop2" : {
"val1" : "value 1 again",
"mask1" : "this will also get masked"
}
}
}
This is what you get:
{
"val1": "value1",
"val2": "value2",
"mask1": "censored",
"prop1": {
"val3": "value3",
"val1": "value1",
"mask2": "censored",
"prop2": {
"val1": "value 1 again",
"mask1": "censored"
}
}
}
To start I would prefer not to use reflection to accomplish this.
I have a class lets say
public class exampleClass
{
public string var1 = "one";
public string var2 = "two";
public int var3 = 3;
public string var4 = "four";
etc. etc..
}
I want to dynamically be able to iterate through that class and print out the variables. I thought about serialization but wasn't exactly sure how to implement it for this case (the only examples I could find were to XML and I don't want that) also I don't really want to change the structure of the class in any way.
The reason I'm doing that is because I'm constructing an HTML table and want to do:
for(int i = 0; i < exampleClass.Count; i++)
tbl_row = "<td>" + exampleClass[i] + "</td>";
or something similar. Any suggestions?
The easisets way would be using reflection. This should be enough :
var example = new exampleClass();
var allPublicFields = example.GetType().
GetFields(BindingFlags.Public | BindingFlags.Instance );
Use a dictionary, instead of fields: Dictionary<fieldName, fieldValue> , but this is
kind over engineering the simple a streghtforward solution: reflection over clear and maintanable structure of your strong typed class.
Complete same for building HTML with TagBuilder.
var tagBuilder = new TagBuilder("tr");
var exampleClass = new exampleClass();
tagBuilder.InnerText += "<td>Field</td><td>Value</td>";
foreach(var field in typeof(exampleClass)
.GetFields(BindingFlags.Public | BindingFlags.Instance))
{
var nameBuilder = new TagBuilder("td");
var valueBuilder = new TagBuilder("td");
nameBuilder.InnerHtml = field.Name;
valueBuilder.InnerHtml = field.GetValue(exampleClass).ToString();
tagBuilder.InnerHtml += string.Format("{0}{1}",
nameBuilder.ToString(),
valueBuilder.ToString());
}
outputs:
<tr>
<td>Field</td><td>Value</td>
<td>var1</td><td>one</td>
<td>var2</td><td>two</td>
<td>var3</td><td>3</td>
<td>var4</td><td>four</td>
<tr>
If you don't want to use reflection, how about storing the data in a dictionary, rather than in a custom class? That way you can simply iterate over the keys or values as required.
Personally, I think you're better off with reflection. You could achieve what you're trying to do if you're using .NET 4 or later and derive exampleClass from DynamicObject.
The example on this page is pretty similar to what you're looking to do.
I've tried looking for an existing question but wasn't sure how to phrase this and this retrieved no results anywhere :(
Anyway, I have a class of "Order Items" that has different properties. These order items are for clothing, so they will have a size (string).
Because I am OCD about these sorts of things, I would like to have the elements sorted not by the sizes as alphanumeric values, but by the sizes in a custom order.
I would also like to not have this custom order hard-coded if possible.
To break it down, if I have a list of these order items with a size in each one, like so:
2XL
S
5XL
M
With alphanumeric sorting it would be in this order:
2XL
5XL
M
S
But I would like to sort this list into this order (from smallest size to largest):
S
M
2XL
5XL
The only way I can think of to do this is to have a hard-coded array of the sizes and to sort by their index, then when I need to grab the size value I can grab the size order array[i] value. But, as I said, I would prefer this order not to be hard-coded.
The reason I would like the order to be dynamic is the order items are loaded from files on the hard disk at runtime, and also added/edited/deleted by the user at run-time, and they may contain a size that I haven't hard-coded, for example I could hard code all the way from 10XS to 10XL but if someone adds the size "110cm" (aka a Medium), it will turn up somewhere in the order that I don't want it to, assuming the program doesn't crash and burn.
I can't quite wrap my head around how to do this.
Also, you could create a Dictionary<int, string> and add Key as Ordering order below. Leaving some gaps between Keys to accomodate new sizes for the future. Ex: if you want to add L (Large), you could add a new item as {15, "L"} without breaking the current order.
Dictionary<int, string> mySizes = new Dictionary<int, string> {
{ 20, "2XL" }, { 1, "S" },
{ 30, "5XL" }, { 10, "M" }
};
var sizes = mySizes.OrderBy(s => s.Key)
.Select(s => new {Size = s.Value})
.ToList();
You can use OrderByDescending + ThenByDescending directly:
sizes.OrderByDescending(s => s == "S")
.ThenByDescending( s => s == "M")
.ThenByDescending( s => s == "2XL")
.ThenByDescending( s => s == "5XL")
.ThenBy(s => s);
I use ...Descending since a true is similar to 1 whereas a false is 0.
I would implement IComparer<string> into your own TShirtSizeComparer. You might have to do some regular expressions to get at the values you need.
IComparer<T> is a great interface for any sorting mechanism. A lot of built-in stuff in the .NET framework uses it. It makes the sorting reusable.
I would really suggest parsing the size string into a separate object that has the size number and the size size then sorting with that.
You need to implement the IComparer interface on your class. You can google how to do that as there are many examples out there
you'll have to make a simple parser for this. You can search inside the string for elements like XS XL and cm" if you then filter that out you have your unit. Then you can obtain the integer that is the value. If you have that you can indeed use an IComparer object but it doesn't have that much of an advantage.
I would make a class out of Size, it is likely that you will need to add more functionality to this in the future. I added the full name of the size, but you could also add variables like width and length, and converters for inches or cm.
private void LoadSizes()
{
List<Size> sizes = new List<Size>();
sizes.Add(new Size("2X-Large", "2XL", 3));
sizes.Add(new Size("Small", "S", 1));
sizes.Add(new Size("5X-Large", "5XL", 4));
sizes.Add(new Size("Medium", "M", 2));
List<string> sizesShortNameOrder = sizes.OrderBy(s => s.Order).Select(s => s.ShortName).ToList();
//If you want to use the size class:
//List<Size> sizesOrder = sizes.OrderBy(s => s.Order).ToList();
}
public class Size
{
private string _name;
private string _shortName;
private int _order;
public string Name
{
get { return _name; }
}
public string ShortName
{
get { return _shortName; }
}
public int Order
{
get { return _order; }
}
public Size(string name, string shortName, int order)
{
_name = name;
_shortName = shortName;
_order = order;
}
}
I implemented TShirtSizeComparer with base class Comparer<object>. Of course you have to adjust it to the sizes and objects you have available:
public class TShirtSizeComparer : Comparer<object>
{
// Compares TShirtSizes and orders them by size
public override int Compare(object x, object y)
{
var _sizesInOrder = new List<string> { "None", "XS", "S", "M", "L", "XL", "XXL", "XXXL", "110 cl", "120 cl", "130 cl", "140 cl", "150 cl" };
var indexX = -9999;
var indexY = -9999;
if (x is TShirt)
{
indexX = _sizesInOrder.IndexOf(((TShirt)x).Size);
indexY = _sizesInOrder.IndexOf(((TShirt)y).Size);
}
else if (x is TShirtListViewModel)
{
indexX = _sizesInOrder.IndexOf(((TShirtListViewModel)x).Size);
indexY = _sizesInOrder.IndexOf(((TShirtListViewModel)y).Size);
}
else if (x is MySelectItem)
{
indexX = _sizesInOrder.IndexOf(((MySelectItem)x).Value);
indexY = _sizesInOrder.IndexOf(((MySelectItem)y).Value);
}
if (indexX > -1 && indexY > -1)
{
return indexX.CompareTo(indexY);
}
else if (indexX > -1)
{
return -1;
}
else if (indexY > -1)
{
return 1;
}
else
{
return 0;
}
}
}
To use it you just have a List or whatever your object is and do:
tshirtList.Sort(new TShirtSizeComparer());
The order you have "hard-coded" is prioritized and the rest is put to the back.
I'm sure it can be done a bit smarter and more generalized to avoid hard-coding it all. You could e.g. look for sizes ending with an "S" and then check how many X's (e.g. XXS) or the number before X (e.g. 2XS) and sort by that, and then repeat for "L" and perhaps other "main sizes".