Using Linq Correct Quiz and Group by Topic - c#

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));
}
}

Related

How to find not matching records in Generic List in C# [duplicate]

This question already has answers here:
Using Linq Except not Working as I Thought
(5 answers)
Closed 4 years ago.
I have two Generic List object, I want to get records which are not matching in second Generic list object. Below is my code. But it returning all records.
I want to ignore matching record in first list.
public class CuratedIncludeUid
{
public string type { get; set; }
public string uid { get; set; }
}
List<CuratedIncludeUid> newUids = new List<CuratedIncludeUid>();
newUids.Add(new CuratedIncludeUid { type = "series", uid = "600" });
List<CuratedIncludeUid> liExistingUids = new List<CuratedIncludeUid>();
liExistingUids.Add(new CuratedIncludeUid { type = "series", uid = "600" });
liExistingUids.Add(new CuratedIncludeUid { type = "series", uid = "200" });
var ied = liExistingUids.Except(newUids).ToList(); ;
foreach (var row in ied)
{
Console.WriteLine("Uid:" + row.uid + "type:" + row.type);
}
Console.Read();
I am getting Output as below
Uid:600type:series
Uid:200type:series
**My expected output as below
Uid:200type:series**
Either override Equals and GetHashCode
public class CuratedIncludeUid
{
public string type { get; set; }
public string uid { get; set; }
protected bool Equals(CuratedIncludeUid other)
{
return string.Equals(type, other.type) && string.Equals(uid, other.uid);
}
public override bool Equals(object obj)
{
if (ReferenceEquals(null, obj)) return false;
if (ReferenceEquals(this, obj)) return true;
return Equals((CuratedIncludeUid) obj);
}
public override int GetHashCode()
{
unchecked
{
return ((type != null ? type.GetHashCode() : 0) * 397) ^ (uid != null ? uid.GetHashCode() : 0);
}
}
}
Or passing an IEqualityComparer to Except
public class CuratedIncludeUidEqualityComparer : IEqualityComparer<CuratedIncludeUid>
{
public bool Equals(CuratedIncludeUid x, CuratedIncludeUid y)
{
if (ReferenceEquals(x, y)) return true;
if (ReferenceEquals(x, null) || ReferenceEquals(y, null)) return false;
return string.Equals(x.type, y.type) && string.Equals(x.uid, y.uid);
}
public int GetHashCode(CuratedIncludeUid obj)
{
unchecked
{
return ((obj.type != null ? obj.type.GetHashCode() : 0) * 397) ^ (obj.uid != null ? obj.uid.GetHashCode() : 0);
}
}
}
var ied = liExistingUids.Except(newUids, new CuratedIncludeUidEqualityComparer()).ToList();
Either, you can implement Equals and GetHashCode or IEqualityComparer, or you can also do the following:
With All:
var ied = liExistingUids.Except(newUids).ToList();
liExistingUids
.Where(x => newUids.All(y => y.type != x.type && y.series != x.series))
.ToList();
With Any:
liExistingUids
.Where(x => !newUids.Any(y => y.type == x.type && y.series == x.series))
.ToList();

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# lambda group query with two parameters? [closed]

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);

Comparison of Objects (Multiple Levels)

I want to create objects with 5 properties and each properties has 2 attributes. After that, I compare the objects if they are same, they will be grouped in same category.
Here is the code:
Item.cs
public class Item
{
public Item()
{
}
public SortProperty SortPropA { get; set; }
public SortProperty SortPropB { get; set; }
public SortProperty SortPropC { get; set; }
public SortProperty SortPropD { get; set; }
public SortProperty SortPropE { get; set; }
public string Name { get; set; }
public string Desc { get; set; }
}
SortProperty.cs
public class SortProperty : IEquatable<SortProperty>
{
public string PartName { get; set; }
public string GroupabilityID { get; set; }
public SortProperty()
{
}
public override int GetHashCode()
{
int hash = 19;
hash = hash * 31 + (GroupabilityID == null ? 0 : GroupabilityID.GetHashCode());
hash = hash * 31 + (PartName == null ? 0 : PartName.GetHashCode());
return hash;
}
public bool Equals(SortProperty obj)
{
return (obj == null) ?
false : (GroupabilityID == obj.GroupabilityID) || (PartName == obj.PartName);
}
public override bool Equals(Object obj)
{
SortProperty itemobj = obj as SortProperty;
return itemobj == null ? false : Equals(itemobj);
}
}
Program.cs (main class to test the coding)
class Program
{
static void Main(string[] args)
{
Item objA = new Item();
Item objB = new Item();
// ------ Object A
objA.Name = "Card1";
objA.Desc = "Product Test A";
//Property A
objA.SortPropA = new SortProperty();
objA.SortPropA.PartName = "Plastic A";
objA.SortPropA.GroupabilityID = "A1";
//Property B
objA.SortPropB = new SortProperty();
objA.SortPropB.PartName = "Color Green";
objA.SortPropB.GroupabilityID = "B2";
//Property C
objA.SortPropC = new SortProperty();
objA.SortPropC.PartName = "Visa";
objA.SortPropC.GroupabilityID = "C1";
// ------ Object B
objB.Name = "Card2";
objB.Desc = "Product Test B";
//Property A
objB.SortPropA = new SortProperty();
objB.SortPropA.PartName = "Plastic B";
objB.SortPropA.GroupabilityID = "A2";
//Property B
objB.SortPropB = new SortProperty();
objB.SortPropB.PartName = "Color Lime";
objB.SortPropB.GroupabilityID = "B1";
//Property C
objB.SortPropC = new SortProperty();
objB.SortPropC.PartName = "Visa";
objB.SortPropC.GroupabilityID = "C1";
bool isEqual = objA.Equals(objB);
if (isEqual == true)
Console.WriteLine("Is same");
else
Console.WriteLine("Is different");
Console.ReadKey();
}
}
The result should return true because there is a same property between objA and objB (SortPropc) but it return false.
I believe I have miss some logic part and I have sitting on chair for 4 hours but couldn't fix it. Can anyone please solve it?
The result should return true because there is a same property between objA and objB (SortPropc) but it return false.
You have just not implemented it. Read your code again and try to find the piece where you actually compare two Item instances. There's is none.
You should implement an Equals and GetHashCode method on your Item class, something like this:
public override bool Equals(Object obj)
{
var o = (Item)obj;
// Note: not error checking :-)
return SortPropA.Equals(o.SortPropA) ||
SortPropB.Equals(o.SortPropB) ||
SortPropC.Equals(o.SortPropC) ||
SortPropD.Equals(o.SortPropD) ||
SortPropE.Equals(o.SortPropE);
}
or create a class that implements IEqualityComparer<Item> that handles this requirement.

MSUnit: Assert.AreEqual fails trees

I have to test the equality of trees. In other other words objects which contains List<T> with childs and the childs also contains List<T> with childs and so on.
I've found that you can test List with CollectionAssert, however it does not work that well with composites.
Any suggestions? MSUnit is my test library.
Example
IReagentComposed bronzeBarParsed = (from n in composedCrafts where n.ItemId == 2841 select n).Single();
IReagentComposed bronzeBar = new Craft()
{
ItemId = 2841,
Profession = Profession.Mining,
Quantity = 0,
QuantityCrafted = 0,
Skill = 50,
Reagents = new List()
{
new Craft()
{
ItemId = 2840,
Quantity = 0,
Skill = 1,
Profession = Profession.Mining,
Reagents = new List()
{
new Reagent()
{
ItemId = 2770,
Quantity = 1
}
}
},
new Craft()
{
ItemId = 3576,
Quantity = 0,
Skill = 50,
Profession = Profession.Mining,
Reagents = new List()
{
new Reagent()
{
ItemId = 2771,
Quantity = 1
}
}
}
}
};
Assert.AreEqual(bronzeBar, bronzeBarParsed);
Craft and Reagent
public class Craft : IReagentComposed
{
public int QuantityCrafted { get; set; }
public int Quantity { get; set;}
public int ItemId { get; set; }
public int Skill { get; set; }
public Profession Profession { get; set; }
public IEnumerable Reagents { get; set; }
public override bool Equals(object other)
{
if (other == null || GetType() != other.GetType()) return false;
IReagentComposed o = other as IReagentComposed;
return o != null && this.Quantity == o.Quantity &&
this.ItemId == o.ItemId &&
this.Profession == o.Profession &&
this.Reagents == o.Reagents && //also tried Equals
this.Skill == o.Skill;
}
public override int GetHashCode()
{
return 0;
}
}
public class Reagent : IReagent
{
public int ItemId { get; set; }
public int Quantity { get; set; }
public override bool Equals(object other)
{
if (other == null || GetType() != other.GetType()) return false;
IReagent o = other as IReagent;
return o != null && o.ItemId == this.ItemId && o.Quantity == this.Quantity;
}
public override int GetHashCode()
{
return 0;
}
}
return o != null && this.Quantity == o.Quantity &&
this.ItemId == o.ItemId &&
this.Profession == o.Profession &&
this.Reagents == o.Reagents && //also tried Equals
this.Skill == o.Skill;
The Reagents are unlikely to match, they are distinct List objects. List<> doesn't override Equals although it isn't that clear what actual type you use. Write a little helper function that takes two lists of reagents and checks for equality. You'd typically start at comparing List<>.Count and then work down the elements one by one.
Added a extension method for IEnumberable<T>:
public static class IEnumberableExtensions
{
public static bool AreEnumerablesEqual<T>(this IEnumerable<T> x, IEnumerable<T> y)
{
if (x.Count() != y.Count()) return false;
bool equals = false;
foreach (var a in x)
{
foreach (var b in y)
{
if (a.Equals(b))
{
equals = true;
break;
}
}
if (!equals)
{
return false;
}
equals = false;
}
return true;
}
}

Categories