Place List<T> values in two arrays - c#

I have the class:
public class DataModel {
public int X { get; set; }
public int Y { get; set; }
}
And the following list:
var data = new List<DataModel>();
data = service.GetData();
I need to change the List to a List:
public class NewDataModel {
public int[] XValues { get; set; }
public int[] YValues { get; set; }
}
So XValues are all the X Values in the original list ... The same with YValues.
How can I do this with Linq?
Thank You,
Miguel

You are expected to post your best try.
var newList = new NewDataModel {
XValues = data.Select(dm => dm.X).ToArray(),
YValues = data.Select(dm => dm.Y).ToArray() };

Untested, but something like this:
var newDataModel = new NewDataModel();
newDataModel.XValues = data.Select(d => d.X).ToArray();
newDataModel.YValues = data.Select(d => d.Y).ToArray();

You should use Aggregate to loop it just once:
newDataModel = data.Select((x,i)=>new{ x, i})
.Aggregate(new NewDataModel(){XValues = new int[data.Count],
YValues = new int[data.Count]},
(a,b)=> {
a.XValues[b.i] = b.x.X;
a.YValues[b.i] = b.x.Y;
return a;
});

Related

Convert List<string> to List<object> in C#

I have a list of string that looks something like this:
var rawData = new List<string>(){ "EUR/USD;123" , "EUR/GBP;321", "BTC/USD;2321"};
I have the following structure:
public class Data
{
public string instrument { get; set; }
public string positions { get; set; }
}
My goal is to have a list of the string data, splited on the ';' char and converted to a list of objects.
var processedData = new List<Data>();
// processedData[0] ( instrument = EUR/USD, positions = 123 )
// processedData[1] ( instrument = EUR/GBP, positions = 321)
// processedData[2] ( instrument = BTC/USD, positions = 2321)
Do you have any idea how can I do this ?
You can try Linq and query rawData:
var processedData = rawData
.Select(item => item.Split(';'))
.Select(items => new Data() {
instrument = items[0],
positions = items[1]
})
.ToList();
foreach(var rawString in rawData){
var split = rawString.Split(";");
processedData.Add(new Data(){
instruments = split[0],
positions = split[1]
});
}
You can try this code below
private static void TestFunc()
{
var rawData = new List<string>() { "EUR/USD;123", "EUR/GBP;321", "BTC/USD;2321" };
var processedData = new List<Data1>();
foreach (var item in rawData)
{
var ins = item.Split(";")[0];
var pos = item.Split(";")[1];
processedData.Add(new Data1(ins, pos));
}
}
you can use linq
void Main()
{
var rawData = new List<string>() { "EUR/USD;123", "EUR/GBP;321", "BTC/USD;2321" };
rawData.Select(s =>
new Data() {instrument= s.Split(";")[0],positions = (s.Split(";").Count() > 1) ? s.Split(";")[1] : null})
.ToList().Dump();
}
public class Data
{
public string instrument { get; set; }
public string positions { get; set; }
}

How to aggregate data, pass and fail as final result?

I have a list of result either having or not having Data plus has Pass and Fail like below,
var results = new List<Result>
{
new Result{Data = new Data{Name = "A"}, Pass = 1, Fail = 0},
new Result{Data = new Data{Name = "B"}, Pass = 3, Fail = 1},
new Result{Pass = 1, Fail = 0}
};
I need to aggregate data and need this as final result output,
var finalResult = new FinalResult
{
Datas = new List<Data> { new Data { Name = "A" }, new Data { Name = "B" } },
TotalPass = 5,
TotalFail = 1,
Divident = 5/1
}
I tried something like below, but totalPass and totalfail, are not coming correct. Plus, how to aggregate Data?
int totalPass = 0;
int totalfail = 0;
var finalResult = new FinalResult();
foreach (var r in results)
{
totalPass += r.Pass;
totalfail += r.Fail;
}
finalResult.TotalFail = totalPass;
finalResult.TotalFail = totalfail;
finalResult.Divident = totalPass / totalfail;
Here are the two classes:
public class FinalResult
{
public List<Data> Datas { get; set; }
public int TotalPass { get; set; }
public int TotalFail { get; set; }
public int Divident { get; set; }
}
public class Result
{
public Data Data { get; set; }
public int Pass { get; set; }
public int Fail { get; set; }
}
public class Data
{
public string Name { get; set; }
}
You can achieve this easily using LINQ:
var finalResult = new FinalResult
{
Datas = results.Where(r => r.Data != null).Select(r => r.Data).ToList(),
TotalPass = results.Sum(r => r.Pass),
TotalFail = results.Sum(r => r.Fail)
};
// Beware of division by zero and integer division.
finalResult.Divident = finalResult.TotalPass / finalResult.TotalFail;
Notes:
You should probably check the value of TotalFail before the division to prevent division by zero.
As Groo mentioned in the comments, Divident should probably be declared as double and you should cast one of the parts to double unless you do want Integer Division.

How do I use LINQ to group & project objects, based on a member dictionary key?

I have a List<Predictions> that I would like to project onto a List<List<PredictionObj>>. These two classes are defined as follows:
public Predictions
{
public Dictionary<string, double> PredictedMetrics { get; private set; }
public DateTime PredictionTimeStamp { get; set; }
public Predictions()
{
PredictedMetrics = new Dictionary<string, double>();
}
}
public class PredictionObj
{
public string PredictedMetricName { get; set; }
public double PredictedMetricValue { get; set; }
public DateTime PredictionTimeStamp { get; set; }
}
For context, each Predictions object in the List<Predictions> list contains a collection (PredictedMetrics) of predicted values for a set of metrics, which were made at PredictionTimeStamp. I'd like to separate each of those metrics into their own list, such that there will be one list (List<PredictionObj>) for every unique PredictedMetrics key in the list. (PredictedMetricName will map to the dictionary's key, PredictedMetricValue will map to the dictionary's value). I'd like to store all of these lists in one List<List<PredictionObj>> list.
Is there a way to accomplish this using LINQ extension methods?
You can copy/paste the source below into LINQPad as an example. I'm looking for LINQ that will accomplish what GenerateSeperateMetricLists is doing:
void Main()
{
DateTime currTime = DateTime.UtcNow;
List<Predictions> records = new List<Predictions>();
Predictions record1 = new Predictions();
record1.PredictedMetrics.Add("metric1", 2.2d);
record1.PredictedMetrics.Add("metric2", 0.2d);
record1.PredictionTimeStamp = currTime;
records.Add(record1);
Predictions record2 = new Predictions();
record2.PredictedMetrics.Add("metric1", 1.2d);
record2.PredictedMetrics.Add("metric2", 0.1d);
record2.PredictionTimeStamp = currTime.AddMinutes(1);
records.Add(record2);
Predictions record3 = new Predictions();
record3.PredictedMetrics.Add("metric1", 3.2d);
record3.PredictedMetrics.Add("metric2", 0.3d);
record3.PredictionTimeStamp = currTime.AddMinutes(2);
records.Add(record3);
Predictions record4 = new Predictions();
record4.PredictedMetrics.Add("metric1", 4.2d);
record4.PredictedMetrics.Add("metric2", 0.4d);
record4.PredictionTimeStamp = currTime.AddMinutes(3);
records.Add(record4);
//What's the LINQ that could replace this method?
GenerateSeperateMetricLists(records).Dump();
}
private static List<List<PredictionObj>> GenerateSeperateMetricLists(List<Predictions> predictionRecords)
{
var predictionMetricLists = new List<List<PredictionObj>>();
foreach (Predictions forecastRecord in predictionRecords)
{
foreach (KeyValuePair<string, double> prediction in forecastRecord.PredictedMetrics)
{
PredictionObj predictionMetric = new PredictionObj
{
PredictedMetricName = prediction.Key,
PredictedMetricValue = prediction.Value,
PredictionTimeStamp = forecastRecord.PredictionTimeStamp
};
var metricList = predictionMetricLists.Where(x => x.First().PredictedMetricName == prediction.Key);
if (metricList.Count() == 0)
{
predictionMetricLists.Add(new List<PredictionObj> {predictionMetric});
}
else
{
metricList.First().Add(predictionMetric);
}
}
}
return predictionMetricLists;
}
private class Predictions
{
public Dictionary<string, double> PredictedMetrics { get; private set; }
public DateTime PredictionTimeStamp { get; set; }
public Predictions()
{
PredictedMetrics = new Dictionary<string, double>();
}
}
private class PredictionObj
{
public string PredictedMetricName { get; set; }
public double PredictedMetricValue { get; set; }
public DateTime PredictionTimeStamp { get; set; }
}
You should first flatten the data into a list of PredictionObj:
var flatList = records
.SelectMany(r => r.PredictedMetrics.Select(p => new PredictionObj
{
PredictedMetricName = p.Key,
PredictedMetricValue = p.Value,
PredictionTimeStamp = r.PredictionTimeStamp
}));
This produces a flat sequence of PredictionObj objects. Now you can group them by PredictedMetricName:
flatList.GroupBy(x => x.PredictedMetricName).Dump();
The query syntax equivalent, in one statement:
(
from r in records
from p in r.PredictedMetrics
select new PredictionObj
{
PredictedMetricName = p.Key,
PredictedMetricValue = p.Value,
PredictionTimeStamp = r.PredictionTimeStamp
} into flatList
group flatList by flatList.PredictedMetricName into fg
select fg
).Dump();
You just need to take each Prediction and project it into a List<PredictionObj> and then convert those into a List<Prediction>:
var ans = records.SelectMany(p => p.PredictedMetrics.Select(pm => new PredictionObj { PredictedMetricName = pm.Key, PredictedMetricValue = pm.Value, PredictionTimeStamp = p.PredictionTimeStamp }))
.GroupBy(p => p.PredictedMetricName)
.Select(g => g.ToList())
.ToList();
Updated for change in OP.

Empty data on List in LinQ Statement

I got this LinQ statement
var daysList = new List<int>(new int[30]);
var model_pdv = db_pdv.Pdv.GroupBy(x => new { Pdv = x.Clave_PDV, Nombre_Pdv = x.Nombre_Pdv})
.Select(x => new DishVM()
{
Clave_PDV = x.Key.Pdv,
Nombre_Pdv = x.Key.Nombre_Pdv,
Days = daysList,
Data = x
}).ToList();
However i dont know why my "Data" List inside my LinQ gets empty values the first time but then i saves the LinQ as it should
This is my DishVm Class:
public class DishVM
{
public string Clave_PDV { get; set; }
public string Nombre_Pdv { get; set; }
public IEnumerable<Pdv> Data { get; set; }
}
And my Pdv class:
public class Pdv
{
public string Clave_PDV { get; set; }
public string Nombre_Pdv { get; set; }
}
How can i avoid the empty Data List?
The type of x within your Select statement is IGrouping, change it to produce a list:
var model_pdv = db_pdv.Pdv.GroupBy(x => new { Pdv = x.Clave_PDV, Nombre_Pdv = x.Nombre_Pdv})
.Select(x => new DishVM()
{
Clave_PDV = x.Key.Pdv,
Nombre_Pdv = x.Key.Nombre_Pdv,
Days = daysList,
Data = x.ToList()
}).ToList();

Selecting several class properties in one query

The following code takes a collection of class C and creates a collection consisting of the values of two properties A and B. A and B are put inside the same collection:
class A
{
public int x { get; set; }
}
class B
{
public int x { get; set; }
}
class C
{
public A A { get; set; }
public B B { get; set; }
}
..........
var items = new List<C>()
{
new C()
{
A = new A() {x = 1},
B = new B() {x = 2}
},
new C()
{
A = new A() {x = 3},
B = new B() {x = 4}
},
};
var qA = from item in items
select (object)item.A;
var qB = from item in items
select (object)item.B;
var qAll = qA.Concat(qB);
Is it possible to do this with one query?
If you really want to flatten properties like that, you can feed arrays to SelectMany():
var qAll = items.SelectMany(item => new object[] { item.A, item.B });
You could use a ForEach:
var qAll = new List<object>();
items.ForEach(item => { qAll.Add(item.A); qAll.Add(item.B) });

Categories

Resources