Reputation: 39364
I need to create a time series with 200 observations of 10 MeasureTypes (1 to 10) and join everything in a list (using C# 7):
var a = Enumerable.Range(1, 200).Select(x => new Measure { MeasureTypeId = 1, Created = DateTime.Now.AddDays(x), Value = (Decimal)(80 * random.NextDouble() + 40) });
var b = Enumerable.Range(1, 200).Select(x => new Measure { MeasureTypeId = 2, Created = DateTime.Now.AddDays(x), Value = (Decimal)(20 * random.NextDouble() + 30) });
// Other measures
var result = a.Union(b).Union(c). ...
What changes from measure to measure is the MeasureId which is incremental and the parameters (80 and 40) to (20 and 30) to ...
Is there a way to simplify this code?
Upvotes: 1
Views: 581
Reputation: 23797
You can do something like this:
var random = new Random();
int[] multipliers = { 80, 20, 30, 50 };
int[] add = { 40, 30, 10, 20 };
var result = Enumerable.Range(1,4).SelectMany(t =>
Enumerable.Range(1, 200).Select(x =>
new Measure {
MeasureTypeId = t,
Created = DateTime.Now.AddDays(x),
Value = (Decimal)(multipliers[t-1] * random.NextDouble() + add[t-1]) }));
Upvotes: 1
Reputation: 158
public class MeasurementType
{
public int Id { get; set; }
public int Parameter1 { get; set; }
public int Parameter2 { get; set; }
}
public class Measurement
{
public int MeasureTypeId { get; set; }
public DateTime Created { get; set; }
public decimal Value { get; set; }
}
public class MeasurementGenerator
{
private List<MeasurementType> MeasurementTypes
{
get
{
return new List<MeasurementType>
{
new MeasurementType() {Id = 1, Parameter1 = 80, Parameter2 = 40},
new MeasurementType() {Id = 2, Parameter1 = 20, Parameter2 = 30},
new MeasurementType() {Id = 3, Parameter1 = 10, Parameter2 = 50},
new MeasurementType() {Id = 4, Parameter1 = 15, Parameter2 = 60},
//and so on
};
}
}
public List<Measurement> GenerateMeasurements(int type)
{
var result = new List<Measurement>();
for (int i = 0; i < 200; i++)
{
var measurementType = MeasurementTypes.First(x => x.Id == type);
result.Add(new Measurement { MeasureTypeId = type, Created = DateTime.Now.AddDays(i), Value = measurementType.Parameter1 * random.NextDouble() + measurementType.Parameter2 });
}
return result;
}
}
Upvotes: 0
Reputation: 8991
Not sure how you are calculating Measure.Value
, however you can use a SelectMany
to effectively CROSS JOIN
two enumerations together:
var result = Enumerable.Range(1, 10)
.SelectMany(x => Enumerable.Range(1, 200), (t, n) => new Measure {
MeasureId = ((t - 1) * 200) + n,
MeasureTypeId = t,
Created = DateTime.Now.AddDays(n),
Value = (decimal)(80 * random.NextDouble() + 40) // Replace with your logic
});
Upvotes: 0
Reputation: 7579
Use a for
loop with an array (or list) of tuples or a custom type to hold the parameters, like the following:
var result = Set.Empty; // Or whatever you use
Tuple<int, int>[] params = {
new Tuple<int, int>(80, 40),
new Tuple<int, int>(20, 30),
// and so on
}
for(int i = 0; i < N; i++) {
result.Union(Enumerable.Range(1, 200).Select(x => new Measure { MeasureTypeId = i + 1, Created = DateTime.Now.AddDays(x), Value = (Decimal)(params[i].Item1 * random.NextDouble() + params[i].Item2) }));
}
// LINQ version
var result = Enumerable.Range(1, N).SelectMany(x => Enumerable.Range(1, 200), (t, n) => new Measure {
MeasureTypeId = t,
Created = DateTime.Now.AddDays(n),
Value = (decimal)(params[t - 1].Item1 * random.NextDouble() + params[t - 1].Item2)
});
You can use C# 7's sugared tuple syntax if you want, I aren't that well versed with it yet.
If your parameters are part of a series, you can skip the tuples entirely.
LINQ version borrowed and modified from @ChrisPickford's answer.
Upvotes: 2