need some help with my foreach to recongonize the empty record and fill the gap with "-";
let's say we have 30min, 45min, 90min, 120min and not 60min in the case:
It can count the total records of each id, let's say the maximum is 5, 30min, 45min, 60min, 90min and 120min.
if there are 3, then it could check which is missing and than can fill with "-".
Same ideia of the script.
List<Treatment> treatment = new List<Treatment>();
treatment.Add(new Treatment { id = 1, treatmentNameId = 11, duration = "30", price = 30 });
treatment.Add(new Treatment { id = 1, treatmentNameId = 11, duration = "45", price = 45 });
treatment.Add(new Treatment { id = 1, treatmentNameId = 11, duration = "60", price = 60 });
treatment.Add(new Treatment { id = 1, treatmentNameId = 2, duration = "30", price = 30 });
//treatment.Add(new Treatment { id = 1, treatmentNameId = 2, duration = "45", price = 45 });
treatment.Add(new Treatment { id = 1, treatmentNameId = 2, duration = "60", price = 60 });
var newList = (from t in treatment
select t)
.AsQueryable().ToList();
List<List> newList= new List<List>();
foreach (var item in newList)
{
if (item.duration == "30")
{
newList.Add(new List { treatmentNameId = item.treatmentNameId, thirtyMin = "30" });
}
if (item.duration == "45")
{
newList.Add(new List { treatmentNameId = item.treatmentNameId, fortyFive= "45" });
}
if (item.duration == "60")
{
newList.Add(new List { treatmentNameId = item.treatmentNameId, sixty= "60" });
}
}
The end result should like something as,
id:1 30, 45, 60, -
id:2 30, - , 60, 90
id:3 - , 45, -, 90
etc...
Many many thanks for the help.
I'm not going to provide a very detailed explanation of all this, but conceptually I'm just grouping by treatmentNameId and then doing something very similar to an outer join in SQL. If the group join comes up empty for the duration, I'm selecting '-' instead of the duration. Using anonymous types for brevity.
var durations = new[] {"15", "30", "45", "60"};
var results = treatments
.GroupBy(t => t.treatmentNameId).Select(group => new
{
treatmentNameId = group.Key,
durations = durations.GroupJoin(group, s => s, g => g.duration,
(s, grouping) => !grouping.Any() ? "-" : s)
});
foreach (var result in results)
{
Console.WriteLine(result.treatmentNameId + ": " + string.Join(", ", result.durations));
}
This results in:
11: -, 30, 45, 60
2: -, 30, -, 60
If you have problems with something more specific, I'd be happy to explain further.
Related
Given a list of values with an unknown number of distinct string values, how do I get the most recent value of Each?
I am given a list of objects with the following three properties: Balance, BalanceType, and CreatedDate. Going in, I know there are a number of distinct values BalanceType can be set to, but I cannot be sure how many distinct values there are. For example, this is a valid input:
[{
"BalanceType":"Cash",
"Balance":350.03,
"CreatedDate":10-20-16
},
{
"BalanceType":"Cash",
"Balance":250.01,
"CreatedDate":10-20-15
},
{
"BalanceType":"Cash",
"Balance":450.21,
"CreatedDate":10-20-14
},
{
"BalanceType":"Securiites",
"Balance":350.03,
"CreatedDate":10-20-16
}]
As is the following:
[{
"BalanceType":"Cash",
"Balance":350.03,
"CreatedDate":10-20-16
},
{
"BalanceType":"Credit",
"Balance":250.01,
"CreatedDate":10-20-15
},
{
"BalanceType":"LoanAmount",
"Balance":450.21,
"CreatedDate":10-20-14
},
{
"BalanceType":"Securiites",
"Balance":350.03,
"CreatedDate":10-20-16
}]
I have already tried using the Max function to do this, but I discovered it only gives the maximum indicated value, not the object. What am I missing?
This Question is related, but in mysql so it isn't usable for me.
It is helpful if you post data in C# format so it can be used directly. Translating your data, here are queries for your answer:
var src1 = new[] {
new {
BalanceType = "Cash",
Balance = 350.03,
CreatedDate = new DateTime(2016, 10, 20)
},
new {
BalanceType = "Cash",
Balance = 250.01,
CreatedDate = new DateTime(2015, 10, 20)
},
new {
BalanceType = "Cash",
Balance = 450.21,
CreatedDate = new DateTime(2014, 10, 20)
},
new {
BalanceType = "Securiites",
Balance = 350.03,
CreatedDate = new DateTime(2016, 10, 20)
}
};
var src2 = new[] {
new {
BalanceType = "Cash",
Balance = 350.03,
CreatedDate = new DateTime(2016, 10, 20)
},
new {
BalanceType = "Credit",
Balance = 250.01,
CreatedDate = new DateTime(2015, 10, 20)
},
new {
BalanceType = "LoanAmount",
Balance = 450.21,
CreatedDate = new DateTime(2014, 10, 20)
},
new {
BalanceType = "Securiites",
Balance = 350.03,
CreatedDate = new DateTime(2016, 10, 20)
}
};
var ans1 = from r in src1
group r by r.BalanceType into rg
let latest = rg.Max(r => r.CreatedDate)
select new { BalanceType = rg.Key, Balance = rg.Where(r => r.CreatedDate == latest).FirstOrDefault().Balance, CreatedDate = latest };
var ans2 = from r in src2
group r by r.BalanceType into rg
let latest = rg.Max(r => r.CreatedDate)
select new { BalanceType = rg.Key, Balance = rg.Where(r => r.CreatedDate == latest).FirstOrDefault().Balance, CreatedDate = latest };
I assumed that if there were more than one latest dated BalanceType, it didn't matter which was chosen, so I used the first. If your DateTimes actually had times you could possibly replace FirstOrDefault() with Single() and crash your program if your assumption is wrong.
Example collection:
List<Product> list = new List<Product>();
list.Add(new Product { Id = 1, Good = 50, Total = 50 });
list.Add(new Product { Id = 2, Good = 18, Total = 30 });
list.Add(new Product { Id = 2, Good = 15, Total = 30 });
list.Add(new Product { Id = 1, Good = 40, Total = 50 });
list.Add(new Product { Id = 3, Good = 6, Total = 10 });
list.Add(new Product { Id = 1, Good = 45, Total = 50 });
list.Add(new Product { Id = 3, Good = 8, Total = 10 });
Number of products is unknown. What I need as a result is to get a percentage for each distinct product good/total, and then an average for all products. In this case:
Product Id=1, GoodSum = 50 + 40 + 45 = 135, TotalSum = 50 + 50 + 50 = 150, Perc = 135/150
Product Id=2, GoodSum = 18 + 15 = 33, TotalSum = 30 + 30 = 60, Perc = 33/60
Product Id=3, GoodSum = 6 + 8 = 14, TotalSum = 10 + 10 = 20, Perc = 14/20
Avg = Avg(135/150 + 35/60 + 14/20) = Avg(0.9 + 0.55 + 0.7) = 2.15 / 3 = 7.17
Can we do this with Linq, I am only interested in Linq solution.
Try this :
var avg = list.GroupBy(G => G.Id)
.Select(G => (G.Sum(T => T.Good)/G.Sum(T => T.TotalSum)))
.Average();
Something like this?
var groups = list.GroupBy(l => l.Id)
.Select(g => new {
Id = g.Key,
GoodSum = g.Sum(i=>i.Good),
TotalSum= g.Sum(i=>i.Total),
Perc = (double) g.Sum(i=>i.Good) / g.Sum(i=>i.Total)
}
);
var average = groups.Average(g=>g.Perc);
Note that your answer for Avg should be 0.717 not 7.17.
var data = new[] {
new { Id = 0, Cat = 1, Price = 2 },
new { Id = 1, Cat = 1, Price = 10 },
new { Id = 2, Cat = 1, Price = 30 },
new { Id = 3, Cat = 2, Price = 50 },
new { Id = 4, Cat = 2, Price = 120 },
new { Id = 5, Cat = 2, Price = 200 },
new { Id = 6, Cat = 2, Price = 1024 },
};
var ranges = new[] { 10, 50, 100, 500 };
Needed output is grouped price count by equal or greater than the range used according categories.
(in one linq statement)
cat range count
-------------------------------------
1 10 2 (In 1. categories there is 2 item that price >= 10(range) [10;30])
2 10 4 (In 2. categories there is 4 item that price >= 10(range) [50;120;200;1024])
2 50 4 ....
2 100 3 ....
2 500 1 (In 2. categories there is 1 item that price >= 500(range) [1024])
Try this:
var data = new[] {
new { Id = 0, Cat = 1, Price = 2 },
new { Id = 1, Cat = 1, Price = 10 },
new { Id = 2, Cat = 1, Price = 30 },
new { Id = 3, Cat = 2, Price = 50 },
new { Id = 4, Cat = 2, Price = 120 },
new { Id = 5, Cat = 2, Price = 200 },
new { Id = 6, Cat = 2, Price = 1024 },
};
var ranges = new[] { 10, 50, 100, 500 };
var result = from r in ranges
from g in data
where g.Price >= r
select new {g.Cat, Price=r};
var groupedData =
from d in result
group d by new{d.Cat, d.Price} into g
select new{Cat=g.Key.Cat, Price=g.Key.Price, TotalCount=g.Count()};
This should work:
var values =
data.SelectMany(x => ranges.Where(y => x.Price >= y)
.Select(y => new { Record = x, Range = y }))
.GroupBy(x => new { Cat = x.Record.Cat, Range = x.Range })
.Select(x => new { Cat = x.Key.Cat, Range = x.Key.Range, Count = x.Count()});
Results:
{ Cat = 1, Range = 10, Count = 2 }
{ Cat = 2, Range = 10, Count = 4 }
{ Cat = 2, Range = 50, Count = 4 }
{ Cat = 2, Range = 100, Count = 3 }
{ Cat = 2, Range = 500, Count = 1 }
If I have a IList with the following data:
{ Price = 220, OtherData = "Zsdd1" },
{ Price = 202, OtherData = "Zddsd2" },
{ Price = 20, OtherData ="S2A4" },
{ Price = 202, OtherData = "ZfdfZ3" },
{ Price = 20, OtherData ="SA4" }
How can I get the max OtherData, in the case above "SA4" and S2A4" will be the max. I want to return the number 4. How can I achieve this?
You can execute LINQ expression, something like this:
list.Where(item => char.IsDigit(item.OrderData.Last())).Max(item => item.OrderData.Last());
I have following Table with records for ActivityLog:
ID, UserId, Category, Created
1 11 DeAssigned 05/10/2012
2 11 LogIn 05/11/2012
3 20 Assigned 06/15/2012
4 11 Assigned 06/10/2012
5 20 DeAssigned 06/13/2012
6 20 Assigned 07/12/2012
7 11 DeAssigned 07/16/2012
8 20 Assigned 08/15/2012
...
now i want to query the Table to create same struct the same Result such as this:
var data = new[] {
new { Month = "05", Assigned = 14, DeAssigned = 5, LogIn=1 },
new { Month = "06", Assigned = 5, DeAssigned = 2, LogIn=0 },
new { Month = "07", Assigned = 50, DeAssigned = 8, LogIn=0 },
new { Month = "08", Assigned = 15, DeAssigned = 1, LogIn=0 }
};
what i have achieved:
var result = (from l in repoA.GetAll()
where l.Created >= System.DateTime.Now.AddYears(-1)
group l by new { l.Created.Value.Month, l.Category }
into groups
orderby groups.Key.Month
select new
{
Month = groups.Key.Month,
Category = groups.Key.Category,
Count = groups.Count()
});
there is not optimal result but count all Activity's grouped by Month:
[0] {Month = 6, Category = Assigned, Count = 2}
[0] {Month = 6, Category = Designed, Count = 1}
[0] {Month = 6, Category = LogIn, Count = 1}
[0] {Month = 7, Category = Assigned, Count = 3}
How can i query my Table to Format my Result in "Horizontal Counted" format?
Or simplier:
var result = (from l in repoA.GetAll()
where l.Created >= System.DateTime.Now.AddYears(-1)
group l by l.Created.Month into groups
orderby groups.Key ascending
select new
{
Month = groups.Key,
Assigned = groups.Where(g => g.Category == "Assigned").Count(),
Deassigned = groups.Where(g => g.Category == "DeAssigned").Count(),
LogIn = groups.Where(g => g.Category == "LogIn").Count()
});