C# lambda group query with two parameters? [closed] - c#

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 9 years ago.
Improve this question
How to get count of cars that are turning in only one side, and count of cars that are turning in both sides using lambda?
public class Car
{
public int Id { get; set; }
public string Name { get; set; }
public Car(int _Id, string _Name)
{
Id = _Id;
Name = _Name;
}
}
public class Turn
{
public int Id { get; set; }
public string Name { get; set; }
public Turn(int _Id, string _Name)
{
Id = _Id;
Name = _Name;
}
}
public class CarTurn
{
public int Id { get; set; }
public Car Car { get; set; }
public Turn Turn { get; set; }
public CarTurn(int _Id, Car _Car, Turn _Turn)
{
Id = _Id;
Car = _Car;
Turn = _Turn;
}
}
.
Car car1 = new Car(1, "VW");
Car car2 = new Car(2, "Volvo");
Car car3 = new Car(3, "BMW");
Turn left = new Turn(1, "Left");
Turn right = new Turn(2, "Right");
CarTurn ct1 = new CarTurn(1, car1, left);
CarTurn ct2 = new CarTurn(2, car1, right);
CarTurn ct3 = new CarTurn(3, car2, right);
CarTurn ct4 = new CarTurn(4, car3, left);
List<CarTurn> data = new List<CarTurn>();
data.Add(ct1);
data.Add(ct2);
data.Add(ct3);
data.Add(ct4);
in this case result should be:
One side: 2
Both Sides: 1
EDIT
var groups = data.GroupBy(x => x.Car.Id);
var bothSides = groups.Count(g=> g.Any(x=> x.Turn.Id == 1) && g.Any(x=> x.Turn.Id == 2));
var oneSide = groups.Count(g=> (g.Any(x=> x.Turn.Id == 1) && !g.Any(x=> x.Turn.Id == 2))
|| (!g.Any(x=> x.Turn.Id == 1) && g.Any(x=> x.Turn.Id == 2)));
this is returning:
bothSides: 1
oneSide: 0

var carTurns = new[] { ct1, ct2, ct3, ct4 };
var groupedCarTurns = carTurns.GroupBy(ct => ct.Car);
var oneSideCount = groupedCarTurns.Count(group =>
group.All(ct => ct.Turn == right) ||
group.All(ct => ct.Turn == left);
var bothSides = groupedCarTurns.Count(group =>
group.Any(ct => ct.Turn == right) &&
group.Any(ct => ct.Turn == left);

Something like this (property names imagined):
var groups = data.GroupBy(x => x.CarId);
var bothSides = groups.Count(g=> g.Any(x=> x.IsLeftTurn) && g.Any(x=> x.IsRightTurn);
var oneSide = groups.Count(g=> (g.Any(x=> x.IsLeftTurn) && !g.Any(x=> x.IsRightTurn))
|| (!g.Any(x=> x.IsLeftTurn) && g.Any(x=> x.IsRightTurn);

Related

Linq group result to list of object

I'm trying group a collection of data by it's State but I'm stuck on the correct way to do this:
FileStateInfoDto
public class FileStateInfoDto : EntityDto<int>
{
public string StateName { get; set; }
public int StateNumber { get; set; }
public int FilesByStateCount { get; set; }
}
FileGroupDto
public class FileGroupDto : EntityDto<int>
{
public int CaseId { get; set; }
public string Name { get; set; }
public string ResourceKey { get; set; }
public bool IsFolder { get; set; }
public int SequenceNumber { get; set; }
public IList<FileStateInfoDto> FileStateInfo { get; set; }
public IList<FileGroupDto> FileGroups { get; set; }
public IList<FileInfoDto> Files { get; set; }
}
Here is the code I have:
return await Context.FileGroups
.Include(g => g.Case).Include(g => g.FileGroups).Include(g => g.Files)
.Where(g => g.Id == fileGroupId &&
g.CaseId == caseId &&
g.Case.CaseState != CaseState.Approved &&
g.Case.CaseState != CaseState.Submitted &&
(g.Case.CaseState != CaseState.Draft || g.Case.CreatorUserId == userId))
.OrderBy(g => g.SequenceNumber)
.Select(g => new FileGroup
{
Id = g.Id,
CaseId = g.CaseId,
Name = g.Name,
ResourceKey = g.ResourceKey,
IsFolder = g.IsFolder,
SequenceNumber = g.SequenceNumber,
FileGroups = g.FileGroups,
FileStateInfo = g.Files.GroupBy(f => f.State), <-- My problem
Files = g.Files.Where(f => f.IsActive && f.State != FileApprovalState.Approved).Select(
f => new File
{
Id = f.Id,
CreationTime = f.CreationTime,
CreatorUserId = f.CreatorUserId,
Title = f.Title,
FileName = f.FileName,
URL = f.URL,
Size = f.Size,
KeepOnPortal = f.KeepOnPortal,
CreatorUserName = Context.Users.FirstOrDefault(u => u.Id == (f.CreatorUserId ?? 0)).UserName,
CreatorUserRole = Context.CasePersons.Where(p => p.CaseId == caseId && p.UserId == f.CreatorUserId).Take(1).Select(p => p.CaseRoleType.Title).FirstOrDefault()
}
).ToList()
}).FirstOrDefaultAsync();
I'm trying to figure out how I should write this line FileStateInfo = g.Files.GroupBy(f => f.State) so it will give the expected result as below.
FileStateInfo = [{"StateName":"Approved","StateNumber":1, "FilesByStateCount":22},
{"StateName":"NotApproved","StateNumber":2, "FilesByStateCount":11}]
The State in g.Files.GroupBy(f => f.State) is an enum that contains Approved and NotApproved
StateName = Name of the State.
StateNumber = The Integer assinged.
FilesByStateCount = The files count by this state.
I hope it's possible because I've been trying to make this for a few days now.
I've tried things like this Post

Using LINQ for JOINs and Sum

I just started working with LINQ. How can I use SUM and LEFT JOIN using LINQ. I am trying to build the query below in LINQ. Is it possible?
SELECT t.TenantID, t.TenantFName, t.TenantLName, t.RentalAmount, t.PetRent, t.HousingAmount, t.UtilityCharge, t.TVCharge, t.SecurityDeposit, t.HOAFee,
t.ParkingCharge, t.StorageCharge, t.ConcessionAmount, t.ConcessionReason, t.TenantEmail, t.TenantPhone, t.CellPhoneProviderID, t.MoveInDate,
p.PropertyID, p.PropertyName,
TotalDebit, HousingDebit, TotalCredit, HousingCredit
FROM Tenants t
JOIN Properties p ON t.PropertyID = p.PropertyID
LEFT JOIN (
Select
TenantID,
SUM(CASE WHEN TransactionTypeID = 1 AND ChargeTypeID != 6 AND TenantTransactionDate <= Now() THEN TransactionAmount ELSE 0 END) AS TotalDebit,
SUM(CASE WHEN TransactionTypeID = 1 AND ChargeTypeID = 6 AND TenantTransactionDate <= Now() THEN TransactionAmount ELSE 0 END) AS HousingDebit,
SUM(CASE WHEN TransactionTypeID = 2 AND ChargeTypeID != 6 AND TenantTransactionDate <= Now() THEN TransactionAmount ELSE 0 END) AS TotalCredit,
SUM(CASE WHEN TransactionTypeID = 2 AND ChargeTypeID = 6 AND TenantTransactionDate <= Now() THEN TransactionAmount ELSE 0 END) AS HousingCredit
From TenantTransactions
Group By TenantID
) sums ON sums.TenantID = t.TenantID
Where t.Prospect = 2
AND t.PropertyID = 1
Thanks
Roughing out an answer and making a few assumptions about your object model, I'd start off by calculating each of the sums individually with something akin to this statement:
var tenantsTotalDebit = tenantTransactions.Where(tt.TenantId == requestedTenantId && tt.TransactionTypeID == 1 && tt.ChargeTypeID != 6 && tt.TenantTransactionDate <= DateTime.Now).Select(tt => tt.TransactionAmount).Sum();
After you've got all the sums, you can create another query that queries the Tenants and, assuming the Tenants object has it's associated Properties as a member, you could combine them in something like this:
var tenantQuery = tenants.Where(t.Prospect == 1 && t.PropertyID ==1).Select(t.TenantID, t.TenantFName, ..., tenantsTotalDebit, tenantsHousingDebit, tenantsTotalCredit, tenantsHousingCredit);
You can include values beyond the object type that you're querying in a Select() method, so you can include the precalculated sums after determining them separately.
I used classes to model you database. See code below
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
namespace ConsoleApplication53
{
class Program
{
static void Main(string[] args)
{
List<Tenants> tenants = new List<Tenants>();
List<Properties> properties = new List<Properties>();
List<TenantTransactions> transactions = new List<TenantTransactions>();
var tenantTransactions = transactions.GroupBy(x => x.TenantID).Select(x => new
{
id = x.Key,
totalDebit = x.Where(y => (y.TransactionTypeID == 1) && (y.ChargeTypeID != 6) && (y.TenantTransactionDate <= DateTime.Now)).Sum(y => y.TransactionAmount),
housingDebit = x.Where(y => (y.TransactionTypeID == 1) && (y.ChargeTypeID == 6) && (y.TenantTransactionDate <= DateTime.Now)).Sum(y => y.TransactionAmount),
totalCredit = x.Where(y => (y.TransactionTypeID == 2) && (y.ChargeTypeID != 6) && (y.TenantTransactionDate <= DateTime.Now)).Sum(y => y.TransactionAmount),
housingCredit = x.Where(y => (y.TransactionTypeID == 2) && (y.ChargeTypeID == 6) && (y.TenantTransactionDate <= DateTime.Now)).Sum(y => y.TransactionAmount)
}).ToList();
var results2 = (from t in tenants
join p in properties on t.PropertyID equals p.PropertyID
join tt in tenantTransactions on t.TenantID equals tt.id into ps
from tt in ps.DefaultIfEmpty()
select new { t = t, p = p, tt = tt })
.Where(x => (x.t.PropertyID == 1) && (x.t.Prospect == 1))
.GroupBy(x => x.t.TenantID)
.Select(x => new {
tenantID = x.Key,
tenantFirstName = x.FirstOrDefault().t.TenantFName,
tenantLastName = x.FirstOrDefault().t.TenantLName,
tenantEmail = x.FirstOrDefault().t.TenantEmail,
tenantPhone = x.FirstOrDefault().t.TenantPhone,
tenantCellPhoneProvider = x.FirstOrDefault().t.CellPhoneProviderID,
properties = x.Select(y => new {
propertyID = y.p.PropertyID,
propertyName = y.p.PropertyName,
rentalAmount = y.t.RentalAmount,
petRent = y.t.PetRent,
houseingAmount = y.t.HousingAmount,
utilityCharge = y.t.UtilityCharge,
tvCharge = y.t.TVCharge,
sercurityDeposit = y.t.SecurityDeposit,
hoaFee = y.t.HousingAmount,
parkingCharge = y.t.ParkingCharge,
storageCharge = y.t.StorageCharge,
concessionAmount = y.t.ConcessionAmount,
concessionReason = y.t.ConcessionReason,
tenantMoveInDate = y.t.MoveInDate
}).ToList(),
totalDebit = x.FirstOrDefault().tt.totalDebit,
housingDebit = x.FirstOrDefault().tt.housingDebit,
totalCredit = x.FirstOrDefault().tt.totalCredit,
housingCredit = x.FirstOrDefault().tt.housingCredit,
}).ToList();
}
}
public class TenantTransactions
{
public int TenantID { get; set; }
public int TransactionTypeID{ get;set;}
public int ChargeTypeID { get;set;}
public DateTime TenantTransactionDate { get;set;}
public decimal TransactionAmount { get;set;}
}
public class Tenants
{
public int PropertyID { get; set; }
public int Prospect { get; set; }
public int TenantID { get; set; }
public string TenantFName { get; set; }
public string TenantLName { get; set; }
public decimal RentalAmount { get; set; }
public decimal PetRent { get; set; }
public decimal HousingAmount { get; set; }
public decimal UtilityCharge { get; set; }
public decimal TVCharge { get; set; }
public decimal SecurityDeposit { get; set; }
public decimal HOAFee { get; set; }
public decimal ParkingCharge { get; set; }
public decimal StorageCharge { get; set; }
public decimal ConcessionAmount { get; set; }
public string ConcessionReason { get; set; }
public string TenantEmail { get; set; }
public string TenantPhone { get; set; }
public string CellPhoneProviderID { get; set; }
public DateTime MoveInDate { get; set; }
}
public class Properties
{
public int PropertyID { get; set; }
public string PropertyName { get; set; }
}
}

Creating a func for better query searching

I am very very new to writing c# using delegates and funcs. Literally watched a pluralsite video an hour ago.
I am trying to write a function that will allow me to write a flexible method for building up a Where clause in my mvc application using EF and IQueryable
To try explain I thought I would write a small example of what I am trying to do as a console application
public static void Main(string[] args)
{
var city1 = new ArgsSearch() {Address = "city1"};
var city2 = new ArgsSearch() { Address = "city2" };
var city1Dealers = DummyDealers().Where(GenerateSearchCriteria<CarDealer>(city1)).ToList();
var city2Dealers = DummyDealers().Where(GenerateSearchCriteria<CarDealer>(city2)).ToList();
foreach (var carDealer in city1Dealers)
{
Console.WriteLine(carDealer.Name);
}
Console.WriteLine("_______________________________________");
foreach (var carDealer in city2Dealers)
{
Console.WriteLine(carDealer.Name);
}
Console.WriteLine("_______________________________________");
}
public static List<CarDealer> DummyDealers()
{
return new List<CarDealer>()
{
new CarDealer() {Address = "city1", Id = 1, Name = "name1"},
new CarDealer() {Address = "city1", Id = 2, Name = "name2"},
new CarDealer() {Address = "city2", Id = 3, Name = "name3"},
new CarDealer() {Address = "city2", Id = 4, Name = "name4"}
};
}
public static Func<TSearch, bool> GenerateSearchCriteria<TSearch>(ArgsSearch args) where TSearch : IBaseModel
{
if (this.GetType() == typeof(CarModel))
{
//return
return e => e.Name == args.Name;// && e.Cost == args.Cost;
}
if (GetType() == typeof(CarDealer))
{
return e => e.Name == args.Name;// && e.Address == args.Address;
}
return e => e.Name==args.Name;
}
public class ArgsSearch
{
public string Name { get; set; }
public string Address { get; set; }
public decimal Cost { get; set; }
}
Am I going down the right track? How do I know that TSearch is either CarModel or CarDealer? allowing my custom search values to be applied.
Thanks for any suggestions and any help would be really appreciated!
You need to cast:
(warning: ugly code ahead)
if (typeof(TSearch) == typeof(CarModel))
{
//return
return e => e.Name == args.Name && ((CarModel)(object)e).Cost == args.Cost;
}
if (typeof(TSearch) == typeof(CarDealer))
{
return e => e.Name == args.Name && ((CarDealer)(object)e).Address == args.Address;
}
return e => e.Name==args.Name;

c# Array copy, resize

I have an array:
static Array results = new[] { new { Id, RoomCount, Cover, Space, Floor,
FloorCount, NameHouse, Price, NameStreet } };
then I have the second one:
var res = (//.......//
select new { f.Id, f.RoomCount, f.Cover, f.Space, f.Floor, f.FloorCount,
h.NameHouse, f.Price, s.NameStreet }).ToArray();
then I wanna copy res to results:
var lres = res.Length;
res.CopyTo(results, lres);
the lenght of the res varies, and the lenght of the results is fixed, cause it is just declared.
I got an exeption: the length of the dest array is too short.
I also tried to resize dest array:
var lres = res.Length;
Array.Resize(results, lres);
Also crashed: The type arguments for method System.Array.Resize<T>(ref T[], int) cannot be inferred from the usage. Try specifying the type arguments explicitly.
Any suggestions?
public partial class Search : System.Web.UI.Page
{
public static int Id { get; set; }
public static int RoomCount { get; set; }
public static string Cover { get; set; }
public static int Space { get; set; }
public static int Floor { get; set; }
public static int FloorCount { get; set; }
public static string NameHouse { get; set; }
public static decimal Price { get; set; }
public static string NameStreet { get; set; }
static Array results = new[] { new { Id, RoomCount, Cover, Space, Floor, FloorCount, NameHouse, Price, NameStreet } };
private Array FormData()
{
//some code
var lng = ht.Length;
while (lng != 0)
{
//
var var = ht[lng - 1];
lng--;
var res = (from f in db.FlatSet
.Where(x => x.RoomCount >= rMin && x.RoomCount <= rMax)
.Where(x => x.Space >= sMin && x.Space <= sMax)
.Where(x => x.Floor >= fMin && x.Floor <= fMax)
.Where(x => x.FloorCount >= fcMin && x.FloorCount <= fcMax)
.Where(x => x.HouseTypeId == var)// || x.HouseTypeId == 2)
.Where(x => x.Price >= pMin && x.Price <= pMax)
.Where(x => x.Rent == r)
join h in db.HouseTypeSet on f.HouseTypeId equals h.Id
join s in db.StreetSet on f.StreetId equals s.Id
select new { f.Id, f.RoomCount, f.Cover, f.Space, f.Floor, f.FloorCount, h.NameHouse, f.Price, s.NameStreet }).ToArray();
var lres = res.Length;
Array.Resize(ref results, lres);
res.CopyTo(results, lres);
}
return results;
}
FIXED:
public class result
{
public int Id { get; set; }
public int RoomCount { get; set; }
public string Cover { get; set; }
public int Space { get; set; }
public int Floor { get; set; }
public int FloorCount { get; set; }
public string NameHouse { get; set; }
public decimal Price { get; set; }
public string NameStreet { get; set; }
}
public partial class Search : System.Web.UI.Page
{
DB_9AB8FB_lisogorEntities db = new DB_9AB8FB_lisogorEntities();
List<result[]> myList = new List<result[]>();
List<result> NewMyList = new List<result>();
}
//////some code
private List<result[]> FormData()//
{
int[] ht = (int[])arr;
var lng = ht.Length;
while (lng != 0)
{
//some code
var var = ht[lng - 1];
lng--;
myList.Add((from f in db.FlatSet
.Where(x => x.RoomCount >= rMin && x.RoomCount <= rMax)
.Where(x => x.Space >= sMin && x.Space <= sMax)
.Where(x => x.Floor >= fMin && x.Floor <= fMax)
.Where(x => x.FloorCount >= fcMin && x.FloorCount <= fcMax)
.Where(x => x.HouseTypeId == var)// || x.HouseTypeId == 2)
.Where(x => x.Price >= pMin && x.Price <= pMax)
.Where(x => x.Rent == r)
join h in db.HouseTypeSet on f.HouseTypeId equals h.Id
join s in db.StreetSet on f.StreetId equals s.Id
select new result{ Id = f.Id, RoomCount = f.RoomCount, Cover = f.Cover, Space = f.Space, Floor = f.Floor,
FloorCount = f.FloorCount, NameHouse = h.NameHouse, Price = f.Price, NameStreet=s.NameStreet }).ToArray());
}
return myList;
}
private void BindData()
{
var i = myList.Count;
while (i != 0)
{
if (myList[i - 1].Length != 0)
{
var j = myList[i - 1].Length;
while (j != 0)
{
NewMyList.Add(myList[i - 1][j-1]);
j--;
}
}
i--;
}
Results1.DataSource = NewMyList;
Results1.DataBind();
}
}
Try putting the explicit type in your Array.Resize<T>:
Array.Resize<String>(ref results, lres);
Then change lres to 0 because lres is the length of the array and the second parameter for CopyTo is the starting index of the destination not the length of the array:
res.CopyTo(results, 0);
The index is the starting index and you start with the last index and that's why destination array was not long enough.
Or use Array.Copy():
Array.Copy(res, results, res.length);
you are using an anonymous type and the cocmpiler doesn't recognize how it will infer the union of the two arrays as the compiler should know the type of the object for which to create the instance
you are getting this exception at
Array.Resize<T>
method which should be strongly typed
Just to understand more
class Program
{
static void Main(string[] args)
{
Array results = new[] { new { RoomCount = "2", Cover = "5", Space = "5", Floor = "5", FloorCount = "5", NameHouse = "5", Price = "5", NameStreet = "5" } };
//with this line not cpmmented does not compile
Array.Resize(ref results, results.Length + 5);
String[] myArr = {"The", "quick", "brown", "fox", "jumps",
"over", "the", "lazy", "dog"};
Array.Resize(ref myArr, myArr.Length + 5);
MyTest[] resultsMyTest = new MyTest[] {new MyTest{RoomCount=3,Cover="Red"}};
//here it will work as the compiler know how to infer it
Array.Resize(ref resultsMyTest, results.Length + 5);
}
public class MyTest
{
public int RoomCount
{
get;
set;
}
public string Cover
{
get;
set;
}
}
}
Hope this help
If you are after a solution for your current code as it is, go with this,
var arguments=new object[] { results, results.Length + res.Length };
var method= typeof(Array).GetMethod("Resize").MakeGenericMethod(res.GetType().GetElementType());
method.Invoke(null,arguments );
var lastIndex = results.Length;
results = arguments[0] as Array;
res.CopyTo(results, lastIndex);
But I strongly suggest you not to do this. But create a class with all those properties and use a List<YourClass> for a clean and maintainable code. A generic Array of anonymous class won't take you long before you are forced to do a complete re-factoring.

Using Linq Correct Quiz and Group by Topic

I have 3 lists and classes:
List<student_Answers> student_answer = new List<student_Answers>
{new student_Answers {id = "1", q1 ="*C", q2= "*D", q3 = "*B", q4= "*A" },
new student_Answers {id = "2", q1 ="*D", q2= "*E", q3 = "*B", q4= "*A" }};
List<answer> correct_answer = new List<answer>
{new answer{r1 ="*C", r2= "*D", r3 = "*B", r4= "*C" }};
List<Topic> topic_question = new List<Topic>
{ new Topic{ q1_topic ="Verb to be", q2_topic= "Verb to be", q3_topic = "Listening", q4_topic= "Listening" }};
I tried:
foreach (var na in student_answer)
{var grade = from n in student_answer where !na.Contains(n) select n;}
It doesn't work and I don't know how group my questions in topics.
Expected Output :
Failed question:
Id= 1 : Failed in question = 4 : Topic = "Listening"
Id= 2 : Failed in question = 1 : Topic = "Verb to be"
Id= 2 : Failed in question = 4 : Topic = "Listening"
Topic percent:
Listening = 2/4 = 50% incorrect
Verb to be = 1/4 = 25% incorrect
Here's some code to point you in the right direction.
public class StudentQuestion : List<Question>
{
public int StudentId { get; set; }
public StudentQuestion(int studentId, IEnumerable<Question> questions)
:base(questions)
{
StudentId = studentId;
}
public bool AddAnswer(int id, string response)
{
Question question = null;
if((question = this.SingleOrDefault(q => q.Id == id)) == null)
return false;
question.Answer = response;
return true;
}
public bool RemoveAnswer(int id)
{
Question question = null;
if((question = this.SingleOrDefault(q => q.Id == id)) == null)
return false;
question.Answer = string.Empty;
return true;
}
public double ScoreTest(IEnumerable<Answer> answers)
{
List<bool> score = this.Join(answers, a1 => a1.Answer.Response, a2 => a2.Response, (a1, a2) => a1.HasCorrectAnswer(a2)).ToList();
return ((double)score.Where(s => s).Count()) / score.Count;
}
}
public class Question
{
public int Id { get; set; }
public string Text { get; set; }
public Answer Answer { get; set; }
public bool HasCorrectAnswer(Answer correctAnswer)
{
return correctAnswer == Answer;
}
}
public class Answer : IEquatable<Answer>
{
public string Response { get; set; }
public bool Equals(Answer answer)
{
if(answer == null) return false;
return string.Compare(this.Response, answer.Response, true) == 0;
}
public override bool Equals(object obj)
{
if(obj == null)
return false;
var answerObj = obj as Answer;
return answerObj == null ? false : Equals(answerObj);
}
public override int GetHashCode()
{
return Response.GetHashCode();
}
public static bool operator == (Answer answer1, Answer answer2)
{
if ((object)answer1 == null || ((object)answer2) == null)
return object.Equals(answer1, answer2);
return answer1.Equals(answer2);
}
public static bool operator != (Answer answer1, Answer answer2)
{
if ((object)answer1 == null || ((object)answer2) == null)
return ! object.Equals(answer1, answer2);
return ! (answer1.Equals(answer2));
}
}

Categories