Have a collection
List<<KeyValuePair<string, Person>>
public class Person
{
public string FirstName { get; set; }
public string LastName { get; set; }
public int MealType { get; set; }
}
patientEffort.Add("1", new Person() { FirstName = "Raja", LastName = "Ram", MealType = 2 });
patientEffort.Add("2", new Person() { FirstName = "Vijay", LastName = "Anthony", MealType = 1 });
patientEffort.Add("2", new Person() { FirstName = "Vijay", LastName = "Anthony", MealType = 2 });
patientEffort.Add("2", new Person() { FirstName = "Vijay", LastName = "Anthony", MealType = 3 });
patientEffort.Add("3", new Person() { FirstName = "Dr", LastName = "APJ", MealType = 1 });
patientEffort.Add("3", new Person() { FirstName = "Dr", LastName = "APJ", MealType = 2 });
patientEffort.Add("3", new Person() { FirstName = "Dr", LastName = "APJ", MealType = 3 });
patientEffort.Add("3", new Person() { FirstName = "Dr", LastName = "APJ", MealType = 4 });
List<int> _listMealType = new List<int>();
If _listMealType= [2] passed then Result will be
{Key: "1", FirstName = "Raja", LastName = "Ram"}
{Key: "2", FirstName = "Vijay", LastName = "Anthony"}
{Key: "3", FirstName = "Dr", LastName = "APJ"}
If _listMealType= [1,2,3] passed then Result will be
{Key: 2, FirstName = "Vijay", LastName = "Anthony"}
{Key: 3, FirstName = "Dr", LastName = "APJ"}
If _listMealType= [1,2,3,4] passed then Result will be
{Key: "3", FirstName = "Dr", LastName = "APJ"} only
Key may be string or int that doesn't matter. May I have linq query for this scenario. I have used All method is linq but not worked.
var query = patientEffort.Where(d => _listMealType.All(x => x == d.Value.MealType)).Select(d => d.Key);
Could you please help me in solving the query issue as soon as possible.
I hope it helps:
var patients = patientEffort.GroupBy(x => x.Value.FirstName);
var result = (from patient in patients let res = patient.Select(note => note.Value.MealType).ToList() where _listMealType.Intersect(res).Count() == _listMealType.Count select patient.First()).ToList();
Here is variant without linq using:
var patients = patientEffort.GroupBy(x => x.Value.FirstName); // group patients by name
foreach (var patient in patients)
{
var res = new List<int>();
foreach (var note in patient) // collect all meal types of current patient
res.Add(note.Value.MealType);
if (_listMealType.Intersect(res).Count() == _listMealType.Count) // if intersection count equal to source meal list - it's our patient.
result.Add(patient.First()); // add information about patient. because we need only name - we can use first record in list.
}
Related
I have the following objects:
var authors1 = new List<Author>() {
new Author{ FirstName = "William", LastName = "Smith" },
new Author{ FirstName = "Fred", LastName = "Jones" }
};
var authors2 = new List<Author>() {
new Author{ FirstName = "Brian", LastName = "Brains" },
new Author{ FirstName = "Billy", LastName = "TheKid" }
};
var books = new List<Book>() {
new Book{ Title = "JAVA", Description = "Description Java", Authors = authors1 },
new Book{ Title = "PHP", Description = "Description PHP", Authors = authors2 },
};
I want to create a subquery filtering by author. I know that I can do something like this:
IEnumerable<Book> list = books.Where(x => x.Authors.Where(j => j.FirstName == "William").Any());
But I would like to use the authors property as string var.
var entity = "Authors"
IEnumerable<Book> list = books.Where(x => x[entity].Where(j => j.FirstName == "William").Any());
This is not working.
I don't understand why you want to do this... But here is one way you could reach what you want with reflection:
public bool HasAuthorWithName(Book book, string authName)
{
// Retrieve list of class' properties
var p = book.GetType().GetProperties();
// Get list of authors prop by name
var entity = "Authors";
var lstAuthors = p.First(x => x.Name == entity).GetValue(book, null) as List<Author>;
// Filter by author's name
if (lstAuthors != null && lstAuthors.Any())
{
return lstAuthors.Any(j => j.FirstName == authName);
}
return false;
}
Now you can call this method:
IEnumerable<Book> list = books.Where(x => HasAuthorWithName(x, "William"));
How to print out all the persons and their pets, using Linq. I only want to print out persons who have pets.
Prefer result be like:
Kate Bed:
Rex
Sally
My not working solution is here:
class Program
{
static void Main(string[] args)
{
result();
}
static void result() {
var list = StaticGenator.getPersons().Where(x => x.Pets != null);
foreach (var person in list)
{
Console.WriteLine(person.Firstname + " " + person.Lastname + ":");
foreach(var pet in list){
Console.WriteLine(" " + pet.Pets);
}
}
}
What i get is:
Kate Bed:
system.collection.generic.list'1[MainLibrary.Pet]
system.collection.generic.list'1[MainLibrary.Pet]
Here is the code to understand what I am asking:
Data is held here:
public static class StaticGenator
{
public static List<Person> getPersons()
{
List<Person> persons = new List<Person>();
persons.Add(new Person() { Firstname = "Sam", Lastname = "Car", BirthDate = new DateTime(2001, 01, 01), PersonId = 1, Sex = Sex.Man });
persons.Add(new Person() { Firstname = "Kate", Lastname = "Bed", BirthDate = new DateTime(1995, 11, 11), PersonId = 2, Sex = Sex.Woman, Pets = new List<Pet>() { new Pet { Firstname = "Rex", BirthDate = new DateTime(2007, 1, 1), Sex = Sex.Man, PetId = 1 }, new Pet { Firstname = "Sally", BirthDate = new DateTime(2004, 2, 1), Sex = Sex.Woman, PetId = 2 } } });
return persons;
}
}
Person Class:
public class Person
{
public int PersonId { get; set; }
public string Firstname { get; set; }
public string Lastname { get; set; }
public DateTime BirthDate { get; set; }
public Sex Sex{ get; set; }
public int Age {
get
{
var age= DateTime.Now.Year - BirthDate.Year;
if (DateTime.Now.Day >= BirthDate.Day && DateTime.Now.Month >= BirthDate.Month)
return age;
else
return age- 1;
}
}
public List<Pet> Pets { get; set; }
}
Pet Class:
public class Pet
{
public int PetId { get; set; }
public String Firstname { get; set; }
public Sex Sex { get; set; }
public DateTime BirthDate { get; set; }
public int Age { get; set; }
}
Sex enum:
public enum Sex{
Man,
Woman
}
foreach (var person in list)
{
Console.WriteLine(person.Firstname + " " + person.Lastname + ":");
foreach(var pet in person.Pets) // iterate over Pets of person
{
Console.WriteLine(" " + pet.Firstname); // write pet's name
}
}
Keep in mind - you can have problem if somebody will add null pet to pets collection or if there is empty pets list. So, probably correct query to get persons with pets is:
var peopleWithPets = from p in StaticGenator.getPersons()
where p.Pets != null &&
p.Pets.Any() &&
p.Pets.All(x => x != null)
select p;
Also use string formatting:
foreach (var person in peopleWithPets)
{
Console.WriteLine("{0} {1}:", person.Firstname, person.Lastname);
foreach(var pet in person.Pets)
Console.WriteLine("\t{0}", pet.Firstname);
}
Also I suggest you to follow Capitalization Styles recommended by MicroSoft.
foreach(var pet in list)
{
Console.WriteLine(" " + pet.Pets);
}
Should be:
foreach(var pet in person.Pets)
{
Console.WriteLine(" " + pet.FirstName);
}
You have to iterate over the pet collection of the current user that is being iterated.
Suppose you have some list (you mentioned above) with your datastructure
List<Person> persons = new List<Person>();
persons.Add(new Person() { Firstname = "Sam", Lastname = "Car", BirthDate = new DateTime(2001, 01, 01), PersonId = 1, Sex = Sex.Man });
persons.Add(new Person() { Firstname = "Kate", Lastname = "Bed", BirthDate = new DateTime(1995, 11, 11), PersonId = 2, Sex = Sex.Woman, Pets = new List<Pet>() { new Pet { Firstname = "Rex", BirthDate = new DateTime(2007, 1, 1), Sex = Sex.Man, PetId = 1 }, new Pet { Firstname = "Sally", BirthDate = new DateTime(2004, 2, 1), Sex = Sex.Woman, PetId = 2 } } });
You can very easily filter as well as write to console with these 4 lines of code
persons.Where(p => p.Pets != null && p.Pets.Any()).ToList().ForEach(p =>
{
Console.WriteLine(p.Firstname + " " + p.Lastname + "\n");
p.Pets.ForEach(pt => Console.WriteLine(pt.Firstname));
});
var output = String.Join("\n", persons.Select(person => $"{person.Firstname} {person.Lastname}"));
Output:
Sam Car
Kate Bed
I have a school project with a one to many relationship (Contact can have many Addresses). But I don't know how to seed it correctly.
In my Data models Contact has a virtual ICollection<Address> Addresses and the address object has the foreign key of ContactId.
So here is my seed data (code first) And i need to make it so when i type in the contacts last name in a search bar it will pull up all the info on that contact (address Info).
So how do i associate the info together in my seed data so when you search it pulls up what it is supposed to?
namespace Success.Data.Migrations
{
public class Seeder
{
public static void Seed(SuccessContext context,
bool seedContacts = true,
bool seedAddresses = true)
{
if (seedContacts) SeedContacts(context);
if (seedAddresses) SeedAddresses(context);
}
private static void SeedContacts(SuccessContext context)
{
context.Contacts.AddOrUpdate(l => l.LastName,
new Contact() { FullName = "Darth Vader", FirstName = "Darth", LastName = "Vader", },
new Contact() { FullName = "Luke Skywalker", FirstName = "Luke", LastName = "Skywalker", },
new Contact() { FullName = "Tony Stark", FirstName = "Tony", LastName = "Stark", },
new Contact() { FullName = "Ricky Bobby", FirstName = "Ricky", LastName = "Bobby", },
new Contact() { FullName = "Trix Rabbit", FirstName = "Trix", LastName = "Rabbit", });
context.SaveChanges();
}
private static void SeedAddresses(SuccessContext context)
{
context.Addresses.AddOrUpdate(h => h.HomeAddress,
new Address() { HomeAddress = "1300 DeathStar", BusinessAddress = "444 Imperial Fleet", PoBox = "PO Box 1335", ContactId = 1, },
new Address() { HomeAddress = "1997 Endor", BusinessAddress = "448 Rebel Fleet", PoBox = "PO Box 1339", ContactId = 2, },
new Address() { HomeAddress = "1224 Malibu Point", BusinessAddress = "657 Stark Industries", PoBox = "PO Box 1337", ContactId = 3, },
new Address() { HomeAddress = "9978 Fast LN.", BusinessAddress = "532 NASCAR Race Track", PoBox = "PO Box 1333", ContactId = 4, },
new Address() { HomeAddress = "9864 Cerial Box LN", BusinessAddress = "8432 Kellog Dr.", PoBox = "PO Box 1338", ContactId = 5, });
context.SaveChanges();
}
}
}
You could have another method that seeds both the contacts and address. You will need an extra if/else switch
if (seedContacts && seedAddresses)
{
SeedContactsAndAddress(context);
}
else
{
if (seedContacts) SeedContacts(context);
if (seedAddresses) SeedAddresses(context);
}
And the SeedContactsAndAddress Method would look like this:
private static void SeedContactsAndAddress(StoreContext context)
{
// Each Address, which I believe is a collection in this case, but there is only
// one, will have to be created and added to each contact.
var addressesForDarthVader = new List<Address>
{
new Address { HomeAddress = "1300 DeathStar", BusinessAddress = "444 Imperial Fleet", PoBox = "PO Box 1335" }
// Add more addresses for Darth Vader if you need to
};
// Rinse and repeat for the other contacts;
context.Contacts.AddOrUpdate(l => l.LastName,
new Contact() { FullName = "Darth Vader", FirstName = "Darth", LastName = "Vader", Addresses = addressesForDarthVader },
new Contact() { FullName = "Luke Skywalker", FirstName = "Luke", LastName = "Skywalker", },
new Contact() { FullName = "Tony Stark", FirstName = "Tony", LastName = "Stark", },
new Contact() { FullName = "Ricky Bobby", FirstName = "Ricky", LastName = "Bobby", },
new Contact() { FullName = "Trix Rabbit", FirstName = "Trix", LastName = "Rabbit", });
context.SaveChanges();
}
I am trying to unit test this code,
public bool IsCityAvailable(Appointment appointment)
{
var city = _customerRepository.Find(appointment.CustomerId).City;
return _employeeRepository.Get.Count(x => x.City == city) > 0;
}
Here is my test,
[SetUp]
public void Setup()
{
MockAppointmentRepository = new Mock<IRepository<Appointment>>();
MockCustomerRepository = new Mock<IRepository<Customer>>();
MockShiftRepository = new Mock<IRepository<Shift>>();
MockEmployeeRepository = new Mock<IRepository<Employee>>();
AppointmentService = new AppointmentService(MockCustomerRepository.Object, MockAppointmentRepository.Object, MockShiftRepository.Object, MockEmployeeRepository.Object);
Customer = new Customer()
{
Address = "88 Taraview Road NE",
City = "Calgary",
Email = "charles.norris#outlook.com",
FirstName = "Charles",
LastName = "Norris",
Id = 1,
Phone = "587-888-8882",
PostalCode = "X1X 1X1",
Province = "AB"
};
Employee1 = new Employee()
{
Address = "12 Saddletowne Road NW",
City = "Calgary",
Email = "johnny.bravo#outlook.com",
FirstName = "John",
LastName = "Bravo",
Id = 2,
Phone = "403-999-2222",
PostalCode = "X1X 1X1",
Province = "AB"
};
Employee2 = new Employee()
{
Address = "12 Saddletowne Road NW",
City = "Calgary",
Email = "johnny.bravo#outlook.com",
FirstName = "John",
LastName = "Bravo",
Id = 2,
Phone = "403-999-2222",
PostalCode = "X1X 1X1",
Province = "AB"
};
Appointment = new Appointment()
{
Id = 1,
Customer = Customer,
CustomerId = Customer.Id,
Employee = Employee1,
EmployeeId = Employee1.Id,
ScheduledTime = new DateTime(2013,10,15,18,30,00)
};
}
[Test]
public void IsCityAvailableShouldReturnAvailableWhenEmployeeInSameCityFound()
{
// ARRANGE
var employees = new List<Employee> { Employee1, Employee2 };
var result = new Mock<IQueryable<Employee>>();
result.Setup(r => r.GetEnumerator()).Returns(employees.GetEnumerator());
MockCustomerRepository.Setup(x => x.Find(It.IsAny<int>())).Returns(Customer);
MockEmployeeRepository.Setup(x => x.Get).Returns(result.Object);
// ACT
AppointmentService.IsCityAvailable(Appointment);
// ASSERT
MockCustomerRepository.Verify(x => x.Find(It.IsAny<int>()), Times.Once);
MockEmployeeRepository.Verify(x => x.Get, Times.Once);
}
I have debugged and stepped through can't find the value null it is referring to, my city variable is correct, the appointment parameter is fully populated. Is there something missing I am not seeing?
This is the output error from the unit test:
System.ArgumentNullException : Value cannot be null. Parameter name:
arguments
Here is the stacktrace:
System.ArgumentNullException : Value cannot be null.
Parameter name: arguments
at System.Linq.Expressions.Expression.RequiresCanRead(Expression expression, String paramName)
at System.Linq.Expressions.Expression.ValidateOneArgument(MethodBase method, ExpressionType nodeKind, Expression arg, ParameterInfo pi)
at System.Linq.Expressions.Expression.ValidateArgumentTypes(MethodBase method, ExpressionType nodeKind, ref ReadOnlyCollection`1 arguments)
at System.Linq.Expressions.Expression.Call(Expression instance, MethodInfo method, IEnumerable`1 arguments)
at System.Linq.Queryable.Count(IQueryable`1 source, Expression`1 predicate)
at Zenwire.Services.AppointmentService.IsCityAvailable(Appointment appointment) in AppointmentService.cs: line 81
at Tests.Unit.Zenwire.Services.AppointmentServiceTests.IsCityAvailableShouldReturnAvailableWhenEmployeeInSameCityFound() in AppointmentServiceTests.cs: line 100
To test that everyhing has been called correctly:
[SetUp]
public void Setup()
{
MockAppointmentRepository = new Mock<IRepository<Appointment>>();
MockCustomerRepository = new Mock<IRepository<Customer>>();
MockShiftRepository = new Mock<IRepository<Shift>>();
MockEmployeeRepository = new Mock<IRepository<Employee>>();
AppointmentService = new AppointmentService(MockCustomerRepository.Object, MockAppointmentRepository.Object, MockShiftRepository.Object, MockEmployeeRepository.Object);
Customer = new Customer()
{
Address = "88 Taraview Road NE",
City = "Calgary",
Email = "charles.norris#outlook.com",
FirstName = "Charles",
LastName = "Norris",
Id = 1,
Phone = "587-888-8882",
PostalCode = "X1X 1X1",
Province = "AB"
};
Employee1 = new Employee()
{
Address = "12 Saddletowne Road NW",
City = "Calgary",
Email = "johnny.bravo#outlook.com",
FirstName = "John",
LastName = "Bravo",
Id = 2,
Phone = "403-999-2222",
PostalCode = "X1X 1X1",
Province = "AB"
};
Employee2 = new Employee()
{
Address = "12 Saddletowne Road NW",
City = "Calgary",
Email = "johnny.bravo#outlook.com",
FirstName = "John",
LastName = "Bravo",
Id = 2,
Phone = "403-999-2222",
PostalCode = "X1X 1X1",
Province = "AB"
};
Appointment = new Appointment()
{
Id = 1,
Customer = Customer,
CustomerId = Customer.Id,
Employee = Employee1,
EmployeeId = Employee1.Id,
ScheduledTime = new DateTime(2013,10,15,18,30,00)
};
}
[Test]
public void IsCityAvailableShouldReturnAvailableWhenEmployeeInSameCityFound()
{
// ARRANGE
MockCustomerRepository.Setup(x => x.Find(It.IsAny<int>())).Returns(Customer);
MockEmployeeRepository.Setup(x => x.Get).Returns(new List<Employee> { Employee1, Employee2 }.AsQueryable());
// ACT
AppointmentService.IsCityAvailable(Appointment);
// ASSERT
MockCustomerRepository.Verify(x => x.Find(It.IsAny<int>()), Times.Once);
MockEmployeeRepository.Verify(x => x.Get, Times.Once);
}
Test the return value:
[Test]
public void IsCityAvailableShouldReturnAvailableWhenEmployeeInSameCityFound()
{
// ARRANGE
MockCustomerRepository.Setup(x => x.Find(It.IsAny<int>())).Returns(Customer);
MockEmployeeRepository.Setup(x => x.Get).Returns(new List<Employee> { Employee1, Employee2 }.AsQueryable());
// ACT
var actual = AppointmentService.IsCityAvailable(Appointment);
// ASSERT
Assert.IsTrue(actual);
}
I'm trying to implement an IEqualityComparer for my object that basically detects if an object is older that another one. The following simpler example will synthesises what i'm trying to accomplish:
class Program
{
static void Main(string[] args)
{
var authorsList = new List<Author>()
{
new Author{ Firstname = "Bob", Lastname = "Smith", Age=11 },
new Author{ Firstname = "Bob", Lastname = "Smith", Age=20 },
new Author{ Firstname = "Bob", Lastname = "Smith", Age=12 },
new Author{ Firstname = "Bob", Lastname = "Smith", Age=14 },
new Author{ Firstname = "Bob", Lastname = "Smith", Age=12 },
new Author{ Firstname = "Fred", Lastname = "Smith", Age=12 },
new Author{ Firstname = "Trevor", Lastname = "Smith", Age=15 },
new Author{ Firstname = "Brian", Lastname = "Smith", Age=11 },
new Author{ Firstname = "Billy", Lastname = "Smith", Age=11 },
};
var authorsListExcept = new List<Author>()
{
new Author{ Firstname = "Bob", Lastname = "Smith", Age=12 },
new Author{ Firstname = "Fred", Lastname = "Smith", Age=12 },
};
var authorsList2 = authorsList
.Except(authorsListExcept, new AuthorUpdatedComparer()).ToList();
}
}
class Author
{
public string Firstname { get; set; }
public string Lastname { get; set; }
public int Age { get; set; }
}
class AuthorUpdatedComparer : IEqualityComparer<Author>
{
public bool Equals(Author x, Author y)
{
return x.Age >= y.Age;
}
public int GetHashCode(Author obj)
{
//Check whether the object is null
if (Object.ReferenceEquals(obj, null)) return 0;
int FirstnameHash = (obj.Firstname ?? "").GetHashCode();
int LastnameHash = (obj.Lastname ?? "").GetHashCode();
int finalResult = FirstnameHash ^ LastnameHash;
return finalResult;
}
}
My authorsList2 result would be:
* Bob Smith with age 20
* Bom Smith with age 14
* Trevor Smith with age 15
* Brian Smith with age 11
* Billy Smith with age 11
But instead of this the Bob Smith with age 14 is not included.
When debugging I reached the conclusion that the Comparer after included Bob Smith with Age 20 start to using it has a comparer excluding then after all the Bob's younger than 20.
This is a strange behavior in my point of view it should only excluded the ones that are younger or with the same age to those included on the authorsListExcept.
I tried to read msdn documentation and what I want it should be supposed to happen:
font: http://msdn.microsoft.com/en-us/library/bb336390(v=vs.100).aspx
Anyone can help me?
Thanks,
Hugo Salgado
The following LINQ query provides the result you expect:
var result =
authorsList.GroupBy(x => Tuple.Create(x.Firstname, x.Lastname))
.SelectMany(g => g.Where(x => authorsListExcept.All(e => e.Firstname != x.Firstname || e.Lastname != x.Lastname || e.Age < x.Age)));
The following query also produces this result. It should perform better:
var result =
authorsList.GroupBy(x => Tuple.Create(x.Firstname, x.Lastname))
.GroupJoin(authorsListExcept, x => x.Key,
x => Tuple.Create(x.Firstname, x.Lastname),
(a, e) => a.Where(x => x.Age > e.Select(z => z.Age)
.DefaultIfEmpty(0)
.Max()))
.SelectMany(x => x)
And a third option (the same as the previous but in query syntax):
var result =
(from a in authorsList
group a by Tuple.Create(a.Firstname, a.Lastname) into g
join e in authorsListExcept on g.Key equals Tuple.Create(e.Firstname, e.Lastname) into er
from age in er.Select(x => x.Age).DefaultIfEmpty()
select g.Where(x => x.Age > age)).SelectMany(x => x);
The interface IEqualityComparer<T> is there to check for equality. It has nothing to do with any ordering. As such, you can't use it in the way you try.
In general: An implementation of this interface should always use the exact same set of properties in both the GetHashCode implementation and the Equals method.
If i have understood what you want try this.
class Program
{
static void Main(string[] args)
{
var authorsList = new List<Author>()
{
new Author{ Firstname = "Bob", Lastname = "Smith", Age=11 },
new Author{ Firstname = "Bob", Lastname = "Smith", Age=20 },
new Author{ Firstname = "Bob", Lastname = "Smith", Age=12 },
new Author{ Firstname = "Bob", Lastname = "Smith", Age=14 },
new Author{ Firstname = "Bob", Lastname = "Smith", Age=12 },
new Author{ Firstname = "Fred", Lastname = "Smith", Age=12 },
new Author{ Firstname = "Trevor", Lastname = "Smith", Age=15 },
new Author{ Firstname = "Brian", Lastname = "Smith", Age=11 },
new Author{ Firstname = "Billy", Lastname = "Smith", Age=11 },
};
var authorsListExcept = new List<Author>()
{
new Author{ Firstname = "Bob", Lastname = "Smith", Age=12 },
new Author{ Firstname = "Fred", Lastname = "Smith", Age=12 },
};
var authorsList2 = authorsList.Where(x => !authorsListExcept.Any(y => y.Firstname == x.Firstname && y.Lastname == x.Lastname && x.Age <= y.Age));
}
}
public class Author
{
public string Firstname { get; set; }
public string Lastname { get; set; }
public int Age { get; set; }
}