Linq query- Collection within a dictonary - c#

I am trying to get result from a dictionary using linq but I am not sure how to do it.
I am trying to write a linq query to get the employee name,salary of the empId=2. Please correct me with the right linq query.
class Program
{
static void Main(string[] args)
{
Dictionary<int, List<Employee>> empDic = new Dictionary<int, List<Employee>>();
var emp = new List<Employee>();
emp.Add(new Employee{EmpID = 1,Name="affsa",Salary=2000}) ;
emp.Add(new Employee { EmpID = 2, Name = "axy",Salary=3000 });
emp.Add(new Employee { EmpID = 3, Name = "xyz",Salary=4000 });
empDic.Add(1,emp);
var selectedEmpDetails = empDic.Values
.Select(r => r.Where(f => f.EmpID ==2))
.ToList();
}
}
public class Employee
{
public string Name { get; set; }
public int EmpID { get; set; }
public int Salary { get; set; }
}

You could try something like this:
var selectedEmpDetails = empDic.SelectMany(x=>x.Value)
.Where(x=>x.EmpId==2)
.Select(x=> new { Name = x.Name, Salary = x.Salary });
Initially we flatten the values of the dictionary in a list of Employee objects.
Then we select the object with the EmpId equals to 2.
Last we select it's name and salary properties.

I would use SelectMany() function in your case so that I get a flattened list of Employee instances. Then try to get the first Employee instance that matches the employee id (if any) with the FirstOrDecault() function.
var selectedEmpDetails = empDic.Values.SelectMany(r => r.Where(f => f.EmpID == 2)).FirstOrDefault();
if(selectedEmpDetails != null)
{
string employeeName = selectedEmpDetails.Name;
int employeeSalary = selectedEmpDetails.Salary;
}

Related

Split datatable to list object C# using LINQ or Entity Framework

I have a datatable which contains some rows as a result of joining two tables using the below query:
SELECT
e.Id AS EmpId,
e.Name AS EmpName,
d.Id AS DeptId,
d.Name AS DeptName
FROM
Departments D
JOIN
Employees E ON D.Id = E.DeptId
On the other hand, I have these classes:
class Employee
{
public int Id { get; set; }
public string Name { get; set; }
public string City { get; set; }
public int DeptId { get; set; }
}
class Department
{
public int Id { get; set; }
public string Name { get; set; }
public virtual List<Employee> Employees { get; set; }
}
So, how can I convert the given datatable to a list of Departments, and each department has its own list of employees and so on ...
The basic solution which does the same requirement, it could be as follows, but it is not a professional one and it might hit the performance with big amount of data, especially if we are talking about multiple joins, not like the provided simple example:
var depts = new List<Department>();
var view = dt.DefaultView.ToTable(true, "DeptId", "DeptName");
foreach (DataRow row in view.Rows)
{
var dep = new Department();
var depEmployees = new List<Employee>();
dep.Id = int.Parse(row["DeptId"].ToString());
dep.Name = row["DeptName"].ToString();
foreach (var emp in dt.AsEnumerable()
.Where(w => int.Parse(w["DeptId"].ToString()) == dep.Id).ToList())
{
depEmployees.Add(new Employee
{
Id = int.Parse(emp["EmpId"].ToString()),
Name = emp["EmpName"].ToString(),
City = emp["City"].ToString(),
DeptId = dep.Id
});
dep.Employees = depEmployees;
}
depts.Add(dep);
}
How about this solution:
var view = dt.DefaultView.ToTable(true, "DeptId", "DeptName");
var departments = view.Rows.OfType<DataRow>()
.ToLookup(row => row["DeptId"])
.Select(group => new Depatment
{
Id = group.Key, // convert somehow
Name = group.First()["DeptName"], // convert somehow
Employees = group.Selec(row => new Employee
{
Id = row["EmpId"], // convert somehow
Name = row["EmpName"] // convert somehow
}).ToList();
}).ToList();
IList<Department> departments =
table.AsEnumerable()
.GroupBy(d => new
{
Id = d.Field<Int32>("DeptId"),
Name = d.Field<String>("DeptName")
})
.Select(grp =>
new Department
{
Id = grp.Key.Id,
Name = grp.Key.Name
}).ToList();
Try following :
List<DataTable> deptTables = dt
.AsEnumerable()
.GroupBy(x => x.Field<int>("DeptId"))
.Select(x => x.CopyToDataTable())
.ToList();
Or create a dictionary
Dictionary<int, DataTable> deptDict = dt.AsEnumerable()
.GroupBy(x => x.Field<int>("DeptId"))
.ToDictionary(x => x.Key, y => y.CopyToDataTable());

How do I get two different type of values from database in C# using LINQ?

want to get id and a value stored against it.
value is in float.
i m trying to sort the value and then show it according to the corresponding id.
public List GetStuCosineSimilarity()
{
Dictionary data = new Dictionary<int,>();
List stuId = new List();
data = (from s in DB.Students
select new
{
id = s.StudentId,
cosine = s.cosineSimilarity
}).ToList();
return stuId;
}
If I understand you right, try this:
// data is your dictionary with id and value
var data = DB.Students.ToDictionary(s => s.StudentId, s => s.cosuneSimilarity);
Then, if you need to return the list of IDs you can do this:
return data.Keys.ToList();
public class Student
{
public int Id { get; set; }
public double? Cosine { get; set; }
}
public List<student> GetStuCosineSimilarity()
{
List<Student> lst = new List<Student>();
lst = (from s in DB.Students
select new Student()
{
Id = s.StudentId,
Cosine = s.cosineSimilarity
}).ToList();
lst = lst.OrderBy(k => k.Cosine).ToList(); // Sorting the float value
return lst;
}

Sort a list using a search string

I am trying to sort a list on the basis of a search string. But there seems to be some issue.
Below is the code:
namespace ListDemo
{
class Program
{
static void Main(string[] args)
{
Employee e1 = new Employee {ID=1,Name="John",City="London" };
Employee e2 = new Employee { ID = 2, Name = "Mary", City = "NY" };
Employee e3 = new Employee { ID = 3, Name = "Dave", City = "Sydney" };
Employee e4 = new Employee { ID = 4, Name = "Kate", City = "Chicago" };
Employee e5 = new Employee { ID = 5, Name = "Sheela", City = "Delhi" };
List<Employee> listEmployee = new List<Employee>();
listEmployee.Add(e1);
listEmployee.Add(e2);
listEmployee.Add(e3);
listEmployee.Add(e4);
listEmployee.Add(e5);
Console.WriteLine("Enter the name via which you wana sort?");
string searchString = Console.ReadLine();
Console.WriteLine("####################Sorted List Starts##############");
var items = from element in listEmployee
orderby element.Name.Equals(searchString)
select element;
foreach (var i in items)
{
Console.WriteLine(i.Name);
}
Console.ReadLine();
}
}
class Employee
{
public int ID { get; set; }
public string Name { get; set; }
public string City { get; set; }
}
}
I have an Employee class with 3 public properties, ID, Name and City.
I created a list of Employees with some dummy data in it.
Now I want the user to enter a search string, which will actually be a name, and if the list contains that name, it should sort the list as according to the search string.
For ex: if a user has entered name as 'John', then the revised list should show John as first item and so on.
The code which I have written behaves abnormally.
Image is attached:
Firstly, sort by equals in descending order (it means, that it will be firt in result), and others sort by ID to save original order (or, you can use any other property for ordering):
var items = listEmployee
.OrderByDescending(e => e.Name.Equals(searchString))
.ThenBy(e => e.ID).ToArray();

Query values in a Dictionary<ObjectId, Class> using LINQ?

Consider the following simple example of Students and Teachers;
// person
public class Person
{
public ObjectId Id { get; set; }
public string Name { get; set; }
public Person() {
Id = ObjectId.GenerateNewId(DateTime.Now);
}
}
// student has a Classroom
public class Student : Person
{
public string Classroom { get; set; }
}
// teacher has a Dictionary<ObjectId, Student> Students
public class Teacher : Person
{
[BsonDictionaryOptions(DictionaryRepresentation.ArrayOfDocuments)]
public Dictionary<ObjectId, Student> Students { get; set; }
public Teacher() {
Students = new Dictionary<ObjectId, Student>();
}
}
class Program
{
static void Main(string[] args)
{
var server = MongoServer.Create("mongodb://localhost/database?safe=true");
var database = server.GetDatabase("sandbox");
var collection = database.GetCollection<Teacher>("teachers");
collection.Drop();
// create students
var s1 = new Student() { Name = "s1", Classroom = "foo" };
var s2 = new Student() { Name = "s2", Classroom = "foo" };
var s3 = new Student() { Name = "s3", Classroom = "baz" };
var s4 = new Student() { Name = "s4", Classroom = "foo" };
// teacher 1
var t1 = new Teacher() { Name = "t1" };
t1.Students.Add(s1.Id, s1);
t1.Students.Add(s2.Id, s2);
collection.Insert(t1);
// teacher 2
var t2 = new Teacher {Name = "t2"};
t2.Students.Add(s3.Id, s3);
collection.Insert(t2);
// add teacher 3
var t3 = new Teacher() {Name = "t3"};
t3.Students.Add(s4.Id, s4);
collection.Insert(t3);
// select via key
var onlyt1 = collection.AsQueryable().Where(t => t.Students.ContainsKey(s1.Id)).ToList();
Console.WriteLine("onlyt1 : {0}", onlyt1.ToJson());
Console.ReadLine();
}
}
I can select via the key (shown above), but how do I find all the teachers who have students with classroom of "foo"? I want to write something like;
// select via value
var shouldBeJustT1andT3 = collection.AsQueryable().Where(t => t.Students.Values.Where(s => s.Classroom == "foo")).ToList();
You can use Any to get any teacher for whom there are students in a given classroom "foo":
List<Teacher> shouldBeJustT1andT3 = collection.Where(
teacher => teacher.Students.Any(student => student.Classroom == "foo")
).ToList();
Edit
Since Mongo's IQueryable isn't supporting Any by default, maybe you could just use Where and Count instead of Any:
List<Teacher> shouldBeJustT1andT3 = collection.Where(
teacher => teacher.Students.Where(student => student.Classroom == "foo").Count() > 0
).ToList();
Can't you have Students of type just ICollection<Person>?
Then you don't need query dictionary's values but flat objects' list, i.e. where s.ID == x && s.Classroom == "blah".
Dictionary makes sense to find object by key only, i.e. t.Students[studentId].
To find teachers: see dbaseman's answer, he's correct.

Linq to objects filtering IN and not in

Looking for an example where I can filter my collection based on some filtering criteria.
I have been looking for some example where given a list /array i can filter a collection.
In the example below in my find method I am trying to filter based on 2 values ,looking for something like an "IN" function any suggestions?
class Program
{
static void Main()
{
//Print all customres that belong to below deparments and match on surname
var criteria=new Criteria
{
Departments = new List<string> {"BusinessAnalyst", "Account"},
Surname = "Bloggs"
};
List<Customer> customers = Repository.Find(criteria);
customers.ForEach(x => Console.WriteLine(string.Format("Surname: {0} Department :{1}", x.Surname,x.Department)));
Console.Read();
}
}
public class Repository
{
public static List<Customer>GetCustomers()
{
return new List<Customer>
{
new Customer { Name = "Jon",Surname="Smith",Department = DepartmentType.Managers},
new Customer{Name = "Bill",Surname = "Gates",Department = DepartmentType.Managers},
new Customer { Name = "Mary",Surname = "Bug",Department = DepartmentType.Developers},
new Customer { Name = "Mark",Surname="Boo",Department = DepartmentType.Account},
new Customer{Name = "Ron",Surname = "Scott",Department = DepartmentType.Managers},
new Customer { Name = "Jonny",Surname = "Dip",Department = DepartmentType.Developers},
new Customer { Name = "Mary",Surname = "Bloggs",Department = DepartmentType.BusinessAnalyst},
new Customer { Name = "Mary",Surname = "Bug",Department = DepartmentType.Account},
new Customer { Name = "Jonny",Surname = "Dip",Department = DepartmentType.Account},
new Customer { Name = "Mary",Surname = "Bloggs",Department = DepartmentType.Managers}
};
}
public static List<Customer> Find(Criteria criteria)
{
List<Customer>customers=Repository.GetCustomers();
//Filter on departments
//ERROR HERE AS I cannot do this "IN" would be fantastic.
customers = customers.Contains(criteria.Departments);
//now filter on name
customers = customers.Where(x => x.Surname == criteria.Surname).ToList();
return customers;
}
}
public enum DepartmentType
{
Account,
Managers,
Developers,
BusinessAnalyst
}
public class Customer
{
public string Name { get; set; }
public string Surname { get; set; }
public DepartmentType Department { get; set; }
}
public class Criteria
{
public Criteria()
{
Departments=new List<string>();
}
public string Name { get; set; }
public string Surname { get; set; }
public List<string> Departments { get; set; }
}
public static List<Customer> Find(Criteria criteria)
{
List<Customer> customers = Repository.GetCustomers();
var customers2 = customers.Where(x => criteria.Departments.Contains(x.Department.ToString()));
var customers3 = customers2.Where(x => x.Surname == criteria.Surname);
return customers3.ToList();
}
But considering you use an enum for the Department (DepartmentType), shouldn't your Criteria class use the same instead of a string?
If you define the criteria.Departments as List<DepartmentType> then you can write
public static List<Customer> Find(Criteria criteria)
{
List<Customer> customers = Repository.GetCustomers();
var customers2 = customers.Where(x => criteria.Departments.Contains(x.Department));
var customers3 = customers2.Where(x => x.Surname == criteria.Surname);
return customers3.ToList();
}
Contains returns a bool defining whether a specified object is contained in a collection. Based on your example, you will need to use Where to filter the customers, then use Contains on the departments:
customers = customers.Where(c => criteria.Departments.Contains(c.Department));
i think you want something like this..
customers = customers.Where(c => criteria.Departments.Contains(c.Department));
You want
Customers.Where(c => criteria.Departments.Contains(c.Department.ToString()))
Not sure if this is what you're looking for but the following:
List<Customer> FilteredCustomers = (from c in customers where Criteria.Departments.Contains(c.deparment) && c.surname == Criteria.Surname select c).ToList();
Would equate to something like this in SQL:
SELECT *
FROM Customers
WHERE Department IN (
List of departments
)
AND Surname = surname
I haven't tested this but I think it should work and bring back what you want.

Categories

Resources