Allowing ad-hoc expressions over IEnumerable<MyObj> - c#

I have the following model
public class Model
{
public string Name {get;set;}
public DateTime HireDate {get;set;}
public decimal Salary {get;set;}
public int Hours {get;set;}
}
Now I have the following List
List<Model> employees = new List<Model>();
I am taking expression string input from user, following are the examples of what user might use
Salary
Salary + 500
Salary * Hours
SUM(Hours)
SUM(Hours * Salary)
SUM(Hours) / MIN (Hours)
I have to process user's expressions into another IEnumerable of either int or decimal, depending on calculation and which type has higher precision, for example The 3rd Expression will generate the following
var result = employees.Select(e => e.Salary * e.Hours)
The 4th one will result into this
var result = employees.Sum(e => e.Hours)
I am currently doing it by first parsing the expression into parse tree and building Expression tree using System.Linq.Expressions namespace. With that approach, there is a lot of code and not easily readable by other developers. Is there any easier way ?

Maybe instead of doing it again you might find some help on (already pretty old) Scott Gu's Blog
Or at least it should give you a good code base to have a look into

Related

fast creation of a calculated column in c#

Let us say I am being given a 'string' formula from another source. Example:
NewCalculatedColumn = (Column1 * Column2)/Column3
I would like to apply this formula to create a calculated column for some data stored as double array (or DataTable - I have freedom here) in memory.
In this particular example, the array/dataset consist of 3 column and has thousands of rows. One option is to use DataColumn.Expressions, if the data is stored in a DataTable, as discussed here. However, this may not be the most efficient way. Any feedback would be very much appreciated. Many thanks!
DataTable is a much heavier data structure than a list of objects (or the more generic IEnumerable<T>), as it is indicated here.
So, if you are not forced into using a DataTable a list of objects that look like the following, can be used:
public ObjectType
{
public double Column1 { get; set; }
public double Column2 { get; set; }
public double Column3 { get; set; }
// avoid division by zero, adjust zero comparison threshold as needed
// also adjust returned value on zero
// using C# 6.0 specific syntax. If not available, use get { return } syntax
public double NewCalculatedColumn => Math.Abs(Column3) > 0.0001 ?
(Column1 * Column2)/Column3
: 0.0;
}
Even if you fetch data as DataTable, you can easily convert it to List<ObjectType> as indicated here.
[EDIT]
Based on comment, if expression can is dynamic, an external library can be used. E.g. NCalc:
public double NewCalculatedColumn
{
get
{
// you can provide a dynamic expression which contains col1, col2 and col3
//TODO: add exception handling
var e = new Expression($"(col1 * col2)/{col3}");
e.Parameters["col1"] = Column1;
e.Parameters["col2"] = Column2;
e.Parameters["col3"] = Column3;
return e.Evaluate();
}
}

How to approach building an expression/condition evaluator GUI?

I have a winforms application that is connected to a database which contains a huge amount of measurement data of different datapoints. The data gets updated every few seconds, old values go to an archive table etc. I'm using EF6 for data access.
Now I need to build a GUI that offers some functionality as follows:
The user should be able to define conditions and/or expressions at runtime that then trigger some actions when true. An example in pseudo-code:
if ([Value of Datapoint 203] >= 45 and (TimeStamp of Datapoint 203 < "07:00am")
and (([Value of Datapoint 525] == 1]) or ([Value of Datapoint 22] < 0)])
then set [Value of Datapoint 1234] to ([Value of 203]/4) //or call a method alternatively
or an even simpler example in natural language (differs from the above):
if it is cold and raining, turn on machine XY
where cold and raining are values of certain datapoints and turn on machine is a method with a given parameter XY.
These expressions need to be saved and then evaluated in regular intervals of some minutes or hours. I did not face such a requirement before and I hardly know where to start. What would be the best practice? Is there maybe some sample code you know of? Or are there even controls or libraries for this?
Update: Breaking it down to something more specific:
Suppose I have a class like this:
class Datapoint
{
public int Id { get; set; }
public DateTime TimeStamp { get; set; }
public int Value { get; set; }
}
During runtime I have two objects of this type, DatapointA and DatapointB. I want to enter the following into a textbox and then click a button:
DatapointA.Value>5 && ( DatapointB.Value==2 || DatapointB.Value==7 )
Depending on the actual values of these objects, I want to evaluate this expression string and get a true or false. Is this possible?

C# Split text array into sub array

I can't seem to find much on this online :(
For my course I have to get text from a grocery.txt file and output an invoice.
The text file looks like this:
regular,bread,2.00,2
regular,milk,2.00,3
regular,cereal,4.00,1
fresh,rump steak,11.99,0.8
fresh,apple,4.60,1.00
fresh,cucumber,2.20,0.936
regular,cream,2.20,1
regular,mustard,3.30,1
fresh,carrots,1.79,1.5
regular,tomato sauce,2.95,1
regular,salt,2.80,1
fresh,bananas,4.00,1.2
Currently I use this method to get the text:
string[] groceryItemsArray = System.IO.File.ReadAllLines(#"C:\C\groceries.txt");
What I get is an array that in stores the entire line (for example "fresh,bananas,4.00,1.2").
I have no idea how to split the array into sub arrays or even whats the best way to go about this. Unfortunately this course task are way too advanced for the little material we have been taught and time we have for this. I have already spend around 6 hours watching videos and getting not very far in learning the advanced stuff.
This is what I am trying to accomplish.
A. Class named grocerrItem. This class has properties:
name and price
this class must have 2 constructors
A. subclass of this is a purchasedItem.
this class has an integer property 'quantity'
one of its methods findCost, calculates the cost of the item, including 10% GST.
the formula for this is price * quantity * 1.1
C. A subclass of this class (purchasedItem), freshItem has
a property weight, a double type.
The findCost method here, uses the formula:wieght * price, as it is not subject to GST.
Groceries.txt contains information as follows:
type(regular or fresh), name, price, quantity/weight - depending on being regular or fresh.
** An invoice should be represented as a collection of grocery items (parent class). This can be done using any container structure i.e. array, list or collection. you will then use iteration
You can just use String.Split which returns you the sub array that you want.
public static void Main()
{
string[] groceryItemsArray = System.IO.File.ReadAllLines(#"C:\C\groceries.txt");
// now split each line content with comma. It'll return you an array (sub-array)
foreach (var line in groceryItemsArray)
{
string[] itemsInLine = line.Split(',');
// Do whatevery you want to do with this.
// e.g. for 1st line itemsInLine array will contains 4 items
// "regular","bread","2.00", "2"
}
}
You can use this code (I'm not sure what exactly you looking for):
/// It's return all text as a single list
var groceryItemsArray = System.IO.File.ReadAllLines(#"C:\C\groceries.txt")
.SelectMany(x => x.Split(new char[]{','} , StringSplitOptions.RemoveEmptyEntries)).ToList() ;
Or if want to return as Child List can use this code:
var groceryItemsArray = System.IO.File.ReadAllLines(#"C:\C\groceries.txt").Select(x =>
new { Child = x.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries) }).ToList();
I didn't really understand what are you trying to output, but here's some basic things I did understand on your question:
(code not tested)
I created a parent class:
class GroceryItem
{
public string ItemName {get;set;}
public decimal Price {get;set;}
public GroceryItem() { }
}
And creates a child class:
class PurchasedItem : GroceryItem
{
public int Quantity { get;set; }
public decimal Cost { get;set; }
public PurchasedItem(string[] item)
{
ItemName = item[1];
Price = decimal.Parse(item[2]);
Quantity = int.Parse(item[3]);
FindCost();
}
private void FindCost()
{
Cost = Price * Quantity * 1.1;
}
}
Using your input to get all groceryItems, you can iterate using foreach loop and collect a list of purchasedItems.
Main()
{
string[] groceryItems = System.IO.File.ReadAllLines(#"C:\C\groceries.txt");
var purchasedItems = new List<PurchasedItem>();
foreach (var item in groceryItems)
{
string[] line = item.Split(',');
purchasedItems.Add(new PurchasedItem(line));
}
}
Well if you didn't understand this basic concept of programming, you better start on this link.

Search algorithm required

I need a c# program ( search algorithm ), ie, When user types a character, the display should update to show all valid choices for the next character and a list of possible matching stations.
Ex: User Input: D A R T, it should display
DARTFORD and DARTMOUTH
Suggested outline is below:
public class Suggestions
{
HashSet<Character> nextLetters { get; set; }
HashSet<String> stations { get; set; }
}
public class StationFinder
{
private static String[] stations = new String[] {"LIVERPOOL LIME STREET", "BIRMINGHAM
NEW STREET", "KINGSTON", " DARTFORD", "DARTMOUTH" };
public Suggestions GetSuggestions( String userInput )
{
// TODO Compute result
Suggestions result = new Suggestions();
return result;
}
}
This is just a suggestion it can be modified as well.
Regards,
Vishnu
I do not know C# personally so I can't help you with the code but what you want to use is called a TRIE. This is a specific type of tree structure for strings. The nice property is you can very see all legal endings given the starting of a string. This is perfect for things like auto suggest etc. and I think is what you want for you thing. just google around for TRIE implementations in C#
What you want is a Ternary search tree look here wikipedia and here c# example

Implementation options of summing, averaging, concatenating, etc items in an IEnumerable

I'm looking for the shortest code to create methods to perform common operations on items in an IEnumerable.
For example:
public interface IPupil
{
string Name { get; set; }
int Age { get; set; }
}
Summing a property - e.g. IPupil.Age in IEnumerable<IPupil>
Averaging a property - e.g. IPupil.Age in IEnumerable<IPupil>
Building a CSV string - e.g. IPupil.Name in IEnumerable<IPupil>
I'm interested in the various approaches to solve these examples: foreach (long hand), delegates, LINQ, anonymous methods, etc...
Sorry for the poor wording, I'm having trouble describing exactly what I'm after!
Summing and averaging: easy with LINQ:
var sum = pupils.Sum(pupil => pupil.Age);
var average = pupils.Average(pupil => pupil.Age);
Building a CSV string - there are various options here, including writing your own extension methods. This will work though:
var csv = string.Join(",", pupils.Select(pupil => pupil.Name).ToArray());
Note that it's tricky to compute multiple things (e.g. average and sum) in one pass over the data with normal LINQ. If you're interested in that, have a look at the Push LINQ project which Marc Gravell and I have written. It's a pretty specialized requirement though.

Categories

Resources