Reputation: 225
I have made a following code to create me a range between two numbers, and data is separated in 7 columns:
private List<double> GetRangeForElements(double minPrice, double maxPrice)
{
double determineRange = Math.Round(maxPrice / 7.00d, 3);
var ranges = new List<double>();
ranges.Insert(0, Math.Round(minPrice, 3));
ranges.Insert(1, determineRange);
for (int i = 2; i < 8; i++)
{
ranges.Insert(i, Math.Round(determineRange * i, 3));
}
return ranges;
}
Now I have list of ranges when I call the method:
var ranges = GetRangeForElements(1,1500);
On the other side now I have the data (a list) that contains following data (properties):
public double TransactionPrice {get;set;}
public int SaleAmount {get;set;}
Input data would be:
Transaction price Sale amount
114.5 4
331.5 6
169.59 8
695.99 14
1222.56 5
Generated range for between 1 and 1500 is:
1
214.28
428.57
642.85
857.14
1071.43
1285.71
1500.00
And the desired output would be:
Range Sales
(1 - 214.28) 12
(214.28 - 428.57) 6
(428.57 - 642.85) 0
(642.85 - 857.14) 14
(857.14 - 1071.43) 0
(1071.43 - 1285.71) 5
(1285.71 - 1500) 0
I've tried something like this:
var priceGroups = _groupedItems.GroupBy(x => ranges.FirstOrDefault(r => r > x.TransactionPrice))
.Select(g => new { Price = g.Key, Sales = g.Sum(x=>x.Sales) })
.ToList();
But this doesn't gives me what I want, the results I receive are completely messed up (I was able to verify the data and results manually)...
Can someone help me out?
P.S. guys, the ranges that have no sales should simply have value set to 0...
@blinkenknight here's a pic of what I'm saying, min price is = 2.45 , max price = 2.45
and the output of the 2nd method you posted is:
Upvotes: 3
Views: 1459
Reputation: 726489
Since GetRangeForElements
returns a List<double>
, you cannot group by it. However, you can group by range index, and then use that index to get the range back:
var rangePairs = ranges.Select((r,i) => new {Range = r, Index = i}).ToList();
var priceGroups = _groupedItems
.GroupBy(x => rangePairs.FirstOrDefault(r => r.Range >= x.TransactionPrice)?.Index ?? -1)
.Select(g => new { Price = g.Key >= 0 ? rangePairs[g.Key].Range : g.Max(x => x.TransactionPrice), Sales = g.Sum(x=>x.Sales) })
.ToList();
Assuming that _groupedItems
is a list, you could also start with ranges, and produce the results directly:
var priceGroups = ranges.Select(r => new {
Price = r
, Sales = _groupedItems.Where(x=>ranges.FirstOrDefault(y=>y >= x.TransactionPrice) == r).Sum(x => x.Sales)
});
Note: Good chances are, your GetRangeForElements
has an error: it assumes that minPrice
is relatively small in comparison to maxPrice / 7.00d
. To see this problem, consider what would happen if you pass minPrice=630
and maxPrice=700
: you will get 630, 100, 200, 300, ...
instead of 630, 640, 650, ...
. To fix this problem, compute (maxPrice - minPrice) / 7.00d
and use it as a step starting at minPrice
:
private List<double> GetRangeForElements(double minPrice, double maxPrice) {
double step = (maxPrice - minPrice) / 7.0;
return Enumerable.Range(0, 8).Select(i => minPrice + i*step).ToList();
}
Upvotes: 3