Create "list" of related properties and pass to method - c#

I have a class with many related properties that need I need to run some simple calculations on. The general structure is:
public class SpecialItem
{
public decimal Value { get; set; }
}
public class Processor
{
public decimal CalcA { get; set; }
public decimal CalcB { get; set; }
public decimal CalcC { get; set; }
public SpecialItem ItemA { get; set; }
public SpecialItem ItemB { get; set; }
public SpecialItem ItemC { get; set; }
public decimal PrevCalcA { get; set; }
public decimal PrevCalcB { get; set; }
public decimal PrevCalcC { get; set; }
public decimal DifferenceA { get; set; }
public decimal DifferenceB { get; set; }
public decimal DifferenceC { get; set; }
private void Subtract()
{//TODO}
}
I need to calculate DifferenceA = PrevCalcA - ItemA.Value - CalcA, then DifferenceB = PrevCalcB - ItemB.Value - CalcB , and so on. What is the best way to do this, ideally having a simple subtractor method (ex: private void Subtract(decimal a, decimal b, decimal c) that can sequentially calculate the Difference properties as you feed it a "list" containing groups of 3 other properties?
The reason I have all these properties is that they each indvidually bind to a ViewModel.
Thanks!

It seems to me that the simplest thing to do is redefine the DifferenceX properties like this:
public decimal DifferenceA
{
get
{
return this.PrevCalcA - this.ItemA.Value - this.CalcA;
}
}
public decimal DifferenceB
{
get
{
return this.PrevCalcB - this.ItemB.Value - this.CalcB;
}
}
public decimal DifferenceC
{
get
{
return this.PrevCalcC - this.ItemC.Value - this.CalcC;
}
}
Or am I missing something in your question?

Related

Deserialize child properties from Json

I am getting the following Json from an API:
{
"name":"xyz",
"interval": "H1",
"points": [
{
"speed": 1431,
"mid": { "h": "1.07904", "l": "1.07872" }
}
]
}
And I created the models:
public class Response {
public String? Name { get; set; }
public IntervalEnum? Interval { get; set; }
public List<Point> Points { get; set; } = new List<Point>();
}
public class Point {
public Double Speed { get; set; }
[JsonPropertyName("mid.h")]
public Double High { get; set; }
[JsonPropertyName("mid.l")]
public Double Low { get; set; }
}
I am getting all values but not High and Low.
How can I parse those values?
JsonPropertyName is for the name of a property and has no relation to the path of the property. In other words, writing [JsonPropertyName("mid.h")] you are targeting a property in an object like this:
{
"mid.h": 5
}
The proper way to resolve this is to write your classes in a way that matches with the actual structure of the data:
public class Response {
public String? Name { get; set; }
public IntervalEnum? Interval { get; set; }
public List<Point> Points { get; set; } = new List<Point>();
}
public class Point {
public Double Speed { get; set; }
[JsonPropertyName("mid")]
public MidPoint MidPoint { get; set; }
}
public class MidPoint {
[JsonPropertyName("h")]
public Double High { get; set; }
[JsonPropertyName("l")]
public Double Low { get; set; }
}
If you want to make Low and High accessible in the way you wrote it, you can write a getter for it:
public class Point {
public Double Speed { get; set; }
[JsonPropertyName("mid")]
public MidPoint MidPoint { get; set; }
public Double High => MidPoint.High;
public Double Low => MidPoint.Low;
}
If this really doesn't suit you, you can implement your own JSON resolver: Can I specify a path in an attribute to map a property in my class to a child property in my JSON?

Dealing with VarVector<Single> Feature column in ML.NET

I have a tricky model I'm trying to normalize for binary classification. Here's an example of the model structure. I renamed a few things just to simplify.
public class Review
{
public bool Label { get; set; }
public ReviewItem ReviewItem { get; set; }
public List<OtherItem> OtherItems { get; set; }
}
public class ReviewItem
{
public string SomeText { get; set; }
public float SomeNumber { get; set; }
public bool SomeBool { get; set; }
}
public class OtherItem
{
public string SomeDifferentText { get; set; }
public float SomeDifferentNumber { get; set; }
public bool SomeDifferentBool { get; set; }
}
There can be any number of OtherItem in the List. This is what I tried to flatten the model a bit.
public class ReviewMlModel
{
public bool Label { get; set; }
public string ReviewItem_SomeText { get; set; }
public float ReviewItem_SomeNumber { get; set; }
public bool ReviewItem_SomeBool { get; set; }
public string[] OtherItem_SomeDifferentText { get; set; }
public float[] OtherItem_SomeDifferentNumber { get; set; }
public bool[] OtherItem_SomeDifferentBool { get; set; }
}
From there I tried this to normalize it:
var data = mlContext.Data.LoadFromEnumerable(allReviews);
var dataPrepEstimator = mlContext.Transforms.Text.FeaturizeText("ReviewItem_SomeText")
.Append(mlContext.Transforms.Text.FeaturizeText("OtherItem_SomeDifferentText"))
.Append(mlContext.Transforms.Conversion.ConvertType("ReviewItem_SomeBool"))
.Append(mlContext.Transforms.Conversion.ConvertType("OtherItem_SomeDifferentBool"))
.Append(mlContext.Transforms.Concatenate("Features",
"ReviewItem_SomeText", "OtherItem_SomeDifferentText", "ReviewItem_SomeBool",
"OtherItem_SomeDifferentBool", "ReviewItem_SomeNumber", "OtherItem_SomeDifferentNumber"));
var transformedData = dataPrepEstimator.Fit(data).Transform(data);
var model = mlContext.BinaryClassification.Trainers.AveragedPerceptron()
.Fit(transformedData);
This gives me the exception on the line where I try to create the model:
Schema mismatch for feature column 'Features': expected Vector<Single>, got VarVector<Single> (Parameter 'inputSchema')
I'm guessing this is due to the fact these arrays all have variable lengths, but I don't see a way to transform the VarVector. Do I need to go make the original allReviews enumerable have the same length array for every array? Or am I way off track with how I flattened the original model?
Looks like it was a combination of changing the arrays to all have the same size, as well as adding [VectorType(size)] attribute to all the array properties.

Generate unique string key based on properties of object (cachekey)

I am simply trying to generate a unique cachekey that takes in the object type and property values
GetHashCode returns different results each time so that wont work, so I have to implement a solution but it has to be fast (I can go through the properties and and concat their values to a string but this might be slow and not the best way to go about it)
Nice To Have:
so if 2 different object types have the exact same properties and same values but they are different classes, they should be different cachekeys (chances of this happening are very slim but just in case)
Here is my code
public interface ICachableRequest
{
string GetCacheKey();
}
public class Object1 : ICachableRequest
{
public int IntValue1 { get; set; }
public double DoubleVal1 { get; set; }
public string StringVal1 { get; set; }
public string GetCacheKey()
{
throw new NotImplementedException();
}
}
public class Object2 : ICachableRequest
{
public int SomeIntValue1 { get; set; }
public double SomeOtherDoubleVal1 { get; set; }
public string MoreStringVal1 { get; set; }
public string MoreStringVal2 { get; set; }
public string MoreStringVal3 { get; set; }
public string MoreStringVal4 { get; set; }
public string GetCacheKey()
{
throw new NotImplementedException();
}
}

C# template methods for template IEnumerable<T>. Is it possible?

Can anybody help me to solve this problem?
I have a base class:
public class BaseShowFilter {
public int TotalCount { get; set; }
public int FromNo { get; set; }
public int ShowCount { get; set; }
public string SortFieldName { get; set; }
public bool SortAsc { get; set; }
}
and a couple of ChildClasses from this base class. Then I have a few of other classes that store in (for example)
IEnumerable<OtherClassXXX> = ....
And I want to apply some filter to all of them using same method implemented in BaseShowFilter:
For example I need
dstList = srcList.Skip(this.FromNo-1).Take(this.ShowCount);
So I need implement in BaseShowFilter one function that will be accept in parameter IEnumerable and will return also IEnumerable
How can I write it? In pure C++ it will be simple as 1,2,3... but here I don't know how can it be done. Result may be something like this:
public class BaseShowFilter {
public int TotalCount { get; set; }
public int FromNo { get; set; }
public int ShowCount { get; set; }
public string SortFieldName { get; set; }
public bool SortAsc { get; set; }
public T FilterList<T>(T SrcList) where T :IEnumerable<> {
return srcList.Skip(this.FromNo-1).Take(this.ShowCount);
}
}
This is the usual way to do it:
public IEnumerable<T> FilterList<T>(IEnumerable<T> source)
{
return source.Skip(this.FromNo - 1).Take(this.ShowCount);
}

How to make a generic list equal another generic list

This is my set up,
class CostPeriodDto : IPeriodCalculation
{
public decimal? a { get; set; }
public decimal? b { get; set; }
public decimal? c { get; set; }
public decimal? d { get; set; }
}
interface IPeriodCalculation
{
decimal? a { get; set; }
decimal? b { get; set; }
}
class myDto
{
public List<CostPeriodDto> costPeriodList{ get; set; }
public List<IPeriodCalculation> periodCalcList
{
get
{
return this.costPeriodList; // compile error
}
}
}
What would be the best way of doing this?
Use Cast<IPeriodCalculation>() :
public class CostPeriodDto : IPeriodCalculation
{
public decimal? a { get; set; }
public decimal? b { get; set; }
public decimal? c { get; set; }
public decimal? d { get; set; }
}
public interface IPeriodCalculation
{
decimal? a { get; set; }
decimal? b { get; set; }
}
public class myDto
{
public List<CostPeriodDto> costPeriodList { get; set; }
public List<IPeriodCalculation> periodCalcList
{
get
{
return this.costPeriodList.Cast<IPeriodCalculation>().ToList();
}
}
}
I believe in C#4, if you were using something implementing IEnumerable<out T>, you could simply do it the way you wrote it, and it would be resolved using Covariance.
class myDto
{
public IEnumerable<CostPeriodDto> costPeriodList{ get; set; }
public IEnumerable<IPeriodCalculation> periodCalcList
{
get
{
return this.costPeriodList; // wont give a compilation error
}
}
}
Try return this.costPeriodList.Cast<IPeriodCalculation>().ToList().
The LINQ methods to cast from one sequence to another will not be equal. That is to say that the following test would fail if you used Cast()/ToList().
Assert.AreSame(myDto.costPeriodList, myDto.periodCalcList);
Furthermore, using those methods means that if you tried to add an item to one collection, they would not be reflected in the other. And every time you called periodCalcList, it would be creating an entirely new collection which could be disastrous depending on how many items, how frequently it's called, etc.
A better solution, in my opinion, is to not use List<T> for holding the CostPeriodDto and instead use a collection derived from Collection<T> and explicitly implement IEnumerable<IPeriodCalculation>. Optionally you could implement IList<IPeriodCalculation> if you needed to.
class CostPeriodDtoCollection :
Collection<CostPeriodDto>,
IEnumerable<IPeriodCalculation>
{
IEnumerable<IPeriodCalculation>.GetEnumerator() {
foreach (IPeriodCalculation item in this) {
yield return item;
}
}
}
class MyDto {
public CostPeriodDtoCollection CostPeriods { get; set; }
public IEnumerable<IPeriodCalculation> PeriodCalcList {
get { return CostPeriods; }
}
}

Categories

Resources