My question is similar too THIS
I have two DataTables:
DataTable 1:
Column 1: Date
Column 2: Requests 1
DataTable 2:
Column 1: Date
Column 2: Requests 2
I need the bellow result:
New DataTable:
Column 1: Date
Column 2: Requests 1
Column 3: Requests 2
Expected Result:
Date Requests 1 Requests 2 Total
15/08/2013 25 40 60
14/08/2013 40 60 100
13/08/2013 40 0 25
12/08/2013 0 80 80
What I did until now:
DataTable Lista_1 = ds.Tables[0];
DataTable Lista_2 = ds.Tables[1];
var myLINQ = from l1 in Lista_1.AsEnumerable()
join l2 in Lista_2.AsEnumerable()
on l1.Field<DateTime>("Date") equals l2.Field<DateTime>("Date")
select new
{
dateRelatorio = l1.Field<DateTime>("Date"),
request1Relatorio = l1.Field<int>("Total"),
request2Relatorio = l2.Field<int>("contagem"),
total = l1.Field<int>("Total") + l2.Field<int>("contagem")
};
And I would like to return an IList collection (System.Collections.IList)
UPDATE
listReturn = new List<Stats>();
public class Stats
{
public DateTime dateRelatorio { get; set; }
public int request1Relatorio { get; set; }
public int request2Relatorio { get; set; }
public int total { get; set; }
}
UPDATE 2
May have dates in List_1 that there is not in List_2 and vice versa, so the Request need to be 0.
If you need this thing to be encapsulated in a method, you should create a class to be returned:
public class DailyReport
{
public DateTime Date {get; set;}
public int Requests1 {get; set;}
public int Requests2 {get; set;}
public int Total // this can be calculated on the fly
{
get {return Requests1 + Requests2; }
}
}
And then do
public List<DailyReport> GetDailyReports(..parameters if needed...)
{
...
var myLINQ = from ...
select new DailyReport {
Date = l1.Field<DateTime>("Date"),
Requests1 = l1.Field<int>("Total"),
Requests2 = l2.Field<int>("contagem"),
};
return myLINQ.ToList();
}
There are some dirty hacks that could enable you to return an collection of anonymous objects, but I would advise against it.
Related
In my web application I am fetching 2 lists of objects from database.
First list of objects Employee
1
Name: Tom
Week1: 1
Week2: 3
Week3: 7
2
Name: Mike
Week1: 2
Week2: 1
Week3: 7
Second list of objects listOfId
1
id: 1
color: green
symbol: AT
2
id: 2
color: red
symbol: TB
3
id: 3
color: blue
symbol: TD
I would like to be able now to display it in a form of table, where for each of the weeks, I display this weeks color and symbol (each week matched on Employee.Week# = listOfId.id)
Something like this
Name | Week1 | Week1 Color | Week1 Symbol | Week2 | Week 2 Color etc...
Tom 1 green AT 3 blue
Mike 2 red TB 1 green
In total I will have constant 20 weeks for each employee.
I considered writing a SQL query which would take in week id, and return color and symbol. But for 50 people * 20 weeks... I would need to run this query 1000 times.
I am looking for better approach to solving this issue
my Models:
public class WeekViewModel
{
public int Id{ get; set; }
public string ShortNAme { get; set; }
public string Description { get; set; }
public int Color { get; set; }
}
}
public class EmployeeWeekViewModel
{
public string full_name { get; set; }
public string location { get; set; }
public int week1 { get; set; }
public int week2 { get; set; }
public int week3 { get; set; }
}
If I'm getting your correct, you have two lists coming from DB:
employeesList which represents the employees with their corresponding weeks ID
weeksList which represents the weeks for an employee.
Now, you want to join these two lists to display the information in a simple table format. I would do something like that:
public class EmployeeWeekViewModel{
public string EmployeeName{get;set;}
public WeekViewModel Week1 {get;set;}
public WeekViewModel Week2 {get;set;}
...
public WeekViewModel Week20 {get;set;}
}
public class WeekViewModel{
public int Id{get;set;}
public string Color{get;set;}
public string Symbol{get;set;}
}
employeesList.Select(t=> new EmployeeWeekViewModel(){
EmployeeName = t.Name,
Week1 = weeksList.FirstOrDefault(w => w.id == t.Week1).Select(w => new WeekViewModel(){
Id = w.id,
Color = w.color,
Symbol = w.symbol
}),
Week2 = weeksList.FirstOrDefault(w => w.id == t.Week2).Select(w => new WeekViewModel(){
Id = w.id,
Color = w.color,
Symbol = w.symbol
}),
...
});
In order to not make a request for each week, I would suggest send to you query a list of week Ids to get them once (checkout this example).
I have a class with the following properties
public class Curve
{
public string CurveName { get; set; }
public string RefSource { get; set; }
public int price1 { get; set; }
public int price2 { get; set; }
public int price3 { get; set; }
public static List<Curve> GetCurveList()
{
List<Curve> data = new List<Curve>()
{
new Curve() { CurveName="Lamar", price1 = 1, price2 = 101,price3=104,RefSource="Tome" },
new Curve() { CurveName="Lamar", price1 = 2, price2 = 201,price3=204,RefSource="Richard" }
}
I need it to get transformed in another list as following properties
curveName=lamar,refSource=richard ,hour=(name of the property of price1, price2,price3)taking integer of the last part of the enclosed property,value associated with the price property
curveName=lamar,refSource=Tom,hour=(name of the property of price1, price2,price3)taking integer of the last part of the enclosed property,value associated with the price property
basically the two items of the source list should result into a new list of 6 rows based on the refsource and each property captioned as price and it need to look like below
Name RefSource Hour Value
lamar tom 1 1
lamar tom 2 101
lamar tom 3 104
lamar richard 1 2
lamar richard 2 201
lamar richard 3 204
The hour column is suffix of property name Price1, price2, price3 in the source list.
Try this:
var query =
from curve in Curve.GetCurveList()
from result in new []
{
new { curve.CurveName, curve.RefSource, Hour = 1, Value = curve.price1 },
new { curve.CurveName, curve.RefSource, Hour = 2, Value = curve.price2 },
new { curve.CurveName, curve.RefSource, Hour = 3, Value = curve.price3 },
}
select result;
That gives me:
I have two objects one is a car object and the other object I use to log how many car objects are on shift and record what properties these cars have.
public class Car
{
public int Id { get; set; }
public bool OnShift { get; set; }
public bool HasExtraBaggageSpace { get; set; }
}
public class Log
{
public DateTime TimeStamp { get; set; }
public int CarId { get; set; }
public bool HasExtraBaggageSpace { get; set; }
}
Every five minutes the app selects all the cars on shift and writes the information to a log object and inserts them into a List Logs.
After three weeks of logging I would now like to return a number which reflects the average of the last three weeks . Example:
How many cars with HasExtraBaggageSpace can I expect on a thursday at 14:00.
public class myApp
{
public class AverageReturnArgs
{
public int Hour { get; set; }
public int Minute { get; set; }
public int Count { get; set; }
}
public AverageReturnArgs GetAverage(List<Log> logs, DateTime TimeReq)
{
int hour = TimeReq.Hour;
int min = TimeReq.Minute;
var average = logs.GroupBy(grpByHourMin => new
{
hour = grpByHourMin.TimeStamp.Hour,
min = grpByHourMin.TimeStamp.Minute
}).Select(av => new AverageReturnArgs()
{
Hour = av.Key.hour,
Minute = av.Key.min,
Count = av.Average(x => x.HasExtraBaggageSpace)
});
}
}
This is producing a compiler error.
Count = av.Average(x => x.HasExtraBaggageSpace)
Any ideas how I could accomplish this?
How would you calculate the average of boolean values ?
I think the Count aggregate should be what you are looking for:
Count = av.Count(x => x.HasExtraBaggageSpace)
EDIT If you mean to calculate the percentage of cars having ExtraBaggageSpace you may try something like this :
Count = av.Average(x => x.HasExtraBaggageSpace ? 1 : 0)
With use of the ternary operator this expression convert your boolean value to an integer and calculate the average (that will be a Double).
EDIT 2
Here is what your line should look like.
Count should be made of type Double.
Count = av.Average(x => av.Count(y=>y.HasExtraBaggageSpace))
EDIT 3
Ok the logic was all wrong :
public AverageReturnArgs GetAverage(List<Log> logs, DateTime TimeReq)
{
int hour = TimeReq.Hour;
int min = TimeReq.Minute;
var average = logs
.Where(log => log.TimeStamp.Hour == hour && log.TimeStamp.Minute == min)
.GroupBy(grp => grp.TimeStamp)
.Select(av => new AverageReturnArgs()
{
Hour = hour,
Minute = min,
Count = av.Average(x => av.Count(y=>y.HasExtraBaggageSpace))
});
}
I have a list that contains about 50 properties of a class. What I'm struggling with is I"m trying to take a count of the distinct values of two properties This "count" number then needs to be added on to the end of the list of each group by.
For example: here is my class
public class ListType
{
public ListType()
{
}
public string ID { get; set; }
public string REGSID { get; set; }
public string county { get; set; }
public string act_loc { get; set; }
public string eviofnd { get; set; }
public string hmonth { get; set; }
public string hisnc { get; set; }
public string hinc { get; set; }
public string FIPS { get; set; }
public decimal back00 {get; set;}
public decimal ann00 { get; set; }
public int countDistinctID {get;set;}
}
I need to take a count of distinct IDS of each distinct FIPS and then that count of the distinct IDS is set to countDistinctID property of each grouped FIPS.
ID FIPS other columns(still need this data though)
4 1 ......
5 2 ....
4 1 ....
4 2 ....
1 3 .....
1 2 ....
2 1 .....
What I need is this...
ID FIPS other columns count
4 1 ...... 2 3 rows with FIPS =1 then 2 distinct ID's per FIPs=1
5 2 .... 3 3 rows w/FIPS=2 3 distinct IDS per FIps=2
4 1 .... 2
4 2 .... 3
1 3 ..... 1 1 row w/fips=3 1 distinct id perFIPS=3
1 2 .... 3
2 1 ..... 2
I've parsed in a file and I write all the columns to a list called List data
what I ultimately need to do after I take count of distinct ID's is then set that count value to countDistinctID of the original "data" list and do that for each distinct FIPS and ID per that distinct FIPS
census.countDistinctID
Try this
var distinct = censu.Select(a => a.Select(x=>x.ID).Distinct().Count());
var censu = data.GroupBy(a => a.FIPS).ToList();
foreach (var grp in censu)
{
var count = grp.Select(p=>p.ID).Distinct().Count();
foreach (var d in grp)
d.countDistinctID = count;
}
I have a list of this object:
public class Customer
{
public int Id { get; set; }
public string EmailAddress { get; set; }
public DateTime ServiceStartDate { get; set; }
public DateTime? BillingStartDate { get; set; }
public string Status { get; set; }
}
In preparation for making a chart displayed on a dashboard I am trying to condense this list into another list of this object:
public class DashboardCustomerConversions
{
public string Month { get; set; }
public int Trials { get; set; }
public int Purchased { get; set; }
}
Where the end result looks something like:
Month Trials Purchases
--------- ------ ---------
Dec 2010 390 250
Jan 2011 345 190
Feb 2011 576 340
I am having a hard time coming up with a LINQ statement that can achieve the desired end result. This statement is very close:
var list = from b in results
group b by new { b.ServiceStartDate.Year, b.ServiceStartDate.Month } into g
select new Test
{
Month = string.Format("{0} {1}", CultureInfo.CurrentCulture.DateTimeFormat.GetMonthName(g.Key.Month), g.Key.Year),
Trials = g.Count(),
Purchased = g.Count()
};
The obvious problem in is the "Purchased = g.Count()" line in that it just repeats the Trials result. I would like to count objects where the BillingStartDate.HasValue is true.
Is there a way to restructure the LINQ to make this work?
Edit: I would prefer a fluent style of syntax but I was unable to get the above to work. Answer in any variation would be great.
You need to pass a condition to the Count method.
Purchased = g.Count(q => q.BillingStartDate.HasValue)
So SLaks had the right solution. Here it is written in fluent syntax:
listOfCustomer.GroupBy(c => new { c.ServiceStartDate.Year, c.ServiceStartDate.Month })
.Select(group => new DashboardCustomerConversions()
{
Month = string.Format("{0} {1}", CultureInfo.CurrentCulture.DateTimeFormat.GetMonthName(group.Key.Month), group.Key.Year),
Trials = group.Count(),
Purchased = group.Count(c => c.BillingStartDate.HasValue)
});