List table contains duplicating elements, how to improve this situation and copy data without duplicates in new list employee using linq?
For example output must be something like:
List<Employee> employee = new List<Employee>();
employee.Add(new Employee
{
Name = "Jhon",
components = new List<Component>
{
new Component { id = "4", work = "clear" },
new Component { id = "10", work = "load" },
new Component { id = "5", work = "convert"},
}
});
But how to do it using linq?
Code:
class Program
{
static void Main(string[] args)
{
List<Table> table = new List<Table>();
table.Add(new Table { Name = "Jhon", id = "4", work = "clear" });
table.Add(new Table { Name = "Jhon", id = "10", work = "load" });
table.Add(new Table { Name = "Jhon", id = "5", work = "convert" });
table.Add(new Table { Name = "Nick", id = "2", work = "load" });
table.Add(new Table { Name = "Nick", id = "7", work = "load" });
table.Add(new Table { Name = "Nick", id = "9", work = "load" });
}
}
public class Empoloyee
{
public string Name { get; set; }
public List<Component> components { get; set; }
}
public class Component
{
public string id { get; set; }
public string work { get; set; }
}
public class Table
{
public string Name { get; set; }
public string id { get; set; }
public string work { get; set; }
}
I guess you want have components grouped by employ name
List<Table> table = new List<Table>();
table.Add(new Table { Name = "Jhon", id = "4", work = "clear" });
table.Add(new Table { Name = "Jhon", id = "10", work = "load" });
table.Add(new Table { Name = "Jhon", id = "5", work = "convert" });
table.Add(new Table { Name = "Nick", id = "2", work = "load" });
table.Add(new Table { Name = "Nick", id = "7", work = "load" });
table.Add(new Table { Name = "Nick", id = "9", work = "load" });
var employee = table.GroupBy(t => t.Name)
.Select(g => new Empoloyee() {Name = g.Key, components = g.Select(t => new Component {id = t.id, work = t.work} ).ToList()})
.ToList();
This LINQ statement will generate the output you want:
List<Empoloyee> employee = table
.GroupBy(t => t.Name)
.Select(t => new Empoloyee() {
Name = t.Key,
components = t.Select(s => new Component() {
id = s.id,
work = s.work
})
.ToList()
})
.ToList();
What you need is Grouping on Name.
var results = table.GroupBy(t=>t.Name)
.Select( s=> new Empoloyee() {
Name = s.Key,
components= s.Select(c=> new Component() { id = c.id, work = c.work}).ToList()
}).ToList();
Working Code
Related
I have a list in memory. I am wishing to filter a collection's items matching with that list. The scenario is like the following:
var memoryList = new List<MyClass>()
{
new MyClass(){ Id = "1", Name ="aaa" },
new MyClass(){ Id = "2", Name ="bbb" },
new MyClass(){ Id = "3", Name ="ccc" }
};
IEnumerable<MyCollection> myDesiredItems = repository.GetItems<MyCollection>(c => memoryList.Any(m => m.Id == c.ItemId && m.Name == c.ItemName)).ToList();
public class MyClass
{
public string Id { get; set; }
public string Name { get; set; }
}
But I get Unsupported filter: Any(...) exception when I run my code. Any suggestion how can I achieve myDesiredItems?
I have the following JSON.
public class Code
{
public string ID { get; set; }
}
public class Country
{
public string CountryID { get; set; }
}
public class Complex
{
public Country Country { get; set; }
public Code Code { get; set; }
public string cText { get; set; }
}
public List<Complex> GetData()
{
List<Complex> Data = new List<Complex>();
Data.Add(new Complex() { Country = new Country() { CountryID = "Australia" }, Code = new Code() { ID = "AU" }, cText = "Australia" });
Data.Add(new Complex() { Country = new Country() { CountryID = "Bermuda" }, Code = new Code() { ID = "BM" }, cText = "Bermuda" });
Data.Add(new Complex() { Country = new Country() { CountryID = "Canada" }, Code = new Code() { ID = "CA" }, cText = "Canada" });
Data.Add(new Complex() { Country = new Country() { CountryID = "France" }, Code = new Code() { ID = "FR" }, cText = "France" });
return Data;
}
I need to get the value of CountryID from the given complex key ("Country.CountryID").
I have tried to get the value using the TryGetValue method in c#. It is doesn't work.
I think I need to split the key and process the Complex JSON and find the nested result.
Could you please suggest how to get the value for the complex object from the given complex key?
It can be done via LINQ like this
var codeIdToFind = "AU";
var result = data.Where(c => c.Code.ID.Equals(codeIdToFind, StringComparison.OrdinalIgnoreCase))
.Select(x => x.Country.CountryID)
.FirstOrDefault();
I'm trying to take a list of doctor with locations. each row contains doctor information along with a location. Doctor "A" might have 3 locations so doctor "A" would have 3 rows. I would like to somehow group using linq to take this list to create a new doctor class with a List.
Here is my initial list. Each row duplicates ProviderId and Name if the provider has more than one location
var providerLocation = new List<ProviderLocation>
{
new ProviderLocation
{
ProviderId = "1",
FirstName = "Provider1",
AddressId = "1",
City = "Des Moines"
},
new ProviderLocation
{
ProviderId = "1",
FirstName = "Provider1",
AddressId = "2",
City = "Urbandale"
},
new ProviderLocation
{
ProviderId = "2",
FirstName = "Provider2",
AddressId = "3",
City = "Dallas"
},
new ProviderLocation
{
ProviderId = "2",
FirstName = "Provider2",
AddressId = "4",
City = "Fort Worth"
}
};
would like it to go into new classs that looks like:
public class Doctor
{
public string ProviderId { get; set; }
public string FirstName { get; set; }
public List<DoctorLocation> Locations { get; set; }
}
public class DoctorLocation
{
public string AddressId { get; set; }
public string City { get; set; }
}
Then I could reference my doctor list by:
var doctorList = List<Doctor>
Is there a way to make this happen using linq without having to loop through the list to manually populate the new classes?
Does this produce your desired result ?
var doctorList = providerLocation
.GroupBy(pl => new { pl.ProviderId, pl.FirstName })
.Select(group => new Doctor()
{
ProviderId = group.Key.ProviderId,
FirstName = group.Key.FirstName,
Locations = group.Select(dl => new DoctorLocation()
{
AddressId = dl.AddressId,
City = dl.City
}).ToList()
})
.ToList();
Result:
This LINQ GroupBy your ProviderLocation, returning a list of IGrouping with key being an anonymous object of ProviderId and FirstName.
We get a Doctor for every IGrouping ( taken from group.Key properties )
Then we do a Select on this IGrouping, returning a DoctorLocation for every Item this IGrouping contains.
You can use the ConvertAll method. This is one way to do it -
public static List<Doctor> MakeDoctorsListFrom(List<ProviderLocation> providerLocations)
{
return providerLocations.ConvertAll<Doctor>((input) => new Doctor()
{
ProviderId = input.ProviderId,
FirstName = input.FirstName,
Locations = new List<DoctorLocation>(){
new DoctorLocation(){
AddressId = input.AddressId,
City = input.City
}
}
});
}
And you call it from your code -
var doctors = MakeDoctorsCollectionFrom(providerLocation);
What's the best way to flatten a query that produces a collection that looks like this?
Instead of two rows for ClaimType Target, I want to produce a linq query or expression that has one row for ClaimType Target with both values of Tools and Compass in the same column.
ClaimType | ClaimValue
Target | Tools;Compass
Any ideas, I'm having a total brain cloud on this!
Here is how I would do this:
var claims = new []
{
new { ClaimType = "Redirect Url", ClaimValue = "https://www.thing.com/" },
new { ClaimType = "Target", ClaimValue = "Tools" },
new { ClaimType = "Target", ClaimValue = "Compass" },
};
var query =
from claim in claims
group claim by claim.ClaimType into claim_groups
select new
{
ClaimType = claim_groups.Key,
ClaimValues = String.Join(";", claim_groups.Select(x => x.ClaimValue)),
};
That will give you this:
Since I don't have the table I have created list of objects to simulate your data I hope this might help
List<item> items = new List<item>();
items.Add(new item { id = 1, name = "A", CliamId = "6", ClaimValue = "Any" });
items.Add(new item { id = 1, name = "Target", CliamId = "8", ClaimValue = "Tools" });
items.Add(new item { id = 1, name = "Target", CliamId = "9", ClaimValue = "Compass" });
var query = from i in items
group i by i.name
into g
select g;
foreach(var item in query)
{
Console.Write(string.Format("{0} ", item.Key));
foreach(var row in item)
{
Console.Write(string.Format("{0} ",row.ClaimValue));
}
Console.WriteLine();
}
Console.ReadLine();
}
// end of the class
}
class item
{
public int id { get; set; }
public string name { get; set; }
public string CliamId { get; set; }
public string ClaimValue { get; set; }
// end of the calss
}
The Result :
If I have the following objects.
public class CFS
{
public string FirstName { get; set; }
public string LastName { get; set; }
public string Email { get; set; }
public IList<Topic> Topics { get; set; }
public IList<Status> Status { get; set; }
}
public class Topic
{
public int ID { get; set; }
public string Name { get; set; }
}
public class Status
{
public int ID { get; set; }
public string Name { get; set; }
}
How can I put it into the following object where Topic.ID == Status.ID && Status.Name = "pass"? The Topic and Status string values would be the Topic.Name and Status.Name values respectively. The list of string can be the FirstName, email, whatever, that part is trivial. I realize Topic and Status expose the same properties but that's just for this example.
public class SelectedTopic
{
public string Topic { get; set; }
public string Status { get; set; }
public IList<string> Person { get; set; }
}
I've tried several combinations of SelectMany, Any, Join and I can't seem to pivot the data the way I want.
I don't know why you would want to do this but here is how:
void Main()
{
List<Topic> topicA = new List<Topic>() { new Topic() { ID = 1, Name = "1" }, new Topic() {ID = 2 , Name = "2"}, new Topic() {ID = 3, Name = "3" } };
List<Topic> topicB = new List<Topic>() { new Topic() { ID = 2, Name = "2" }, new Topic() {ID = 3 , Name = "3"}, new Topic() {ID = 4, Name = "4" } };
List<Topic> topicC = new List<Topic>() { new Topic() { ID = 1, Name = "1" } };
List<Topic> topicD = new List<Topic>() { new Topic() {ID = 2 , Name = "2"}, new Topic() {ID = 3, Name = "3" } };
List<Status> statusA = new List<Status>() { new Status() { ID = 1, Name = "pass" }, new Status() {ID = 2 , Name = "2"}, new Status() {ID = 3, Name = "3" } };
List<Status> statusB = new List<Status>() { new Status() { ID = 2, Name = "2" }, new Status() {ID = 3 , Name = "pass"}, new Status() {ID = 4, Name = "pass" } };
List<Status> statusC = new List<Status>() { new Status() { ID = 1, Name = "pass" } };
List<Status> statusD = new List<Status>() { new Status() {ID = 2 , Name = "2"}, new Status() {ID = 3, Name = "pass" } };
List<CFS> test = new List<CFS>() {
new CFS() { FirstName = "A", LastName = "A", Email = "A#A.com", Topics = topicA, Status = statusA },
new CFS() { FirstName = "B", LastName = "B", Email = "B#B.com", Topics = topicB, Status = statusB },
new CFS() { FirstName = "C", LastName = "C", Email = "C#C.com", Topics = topicC, Status = statusC },
new CFS() { FirstName = "D", LastName = "D", Email = "D#D.com", Topics = topicD, Status = statusD },
};
var result = test.SelectMany(x => x.Topics.SelectMany((t) => x.Status, (topic,status) => new { CFS = x, T = topic, S = status }))
.Where(x => x.S.Name == "pass" && x.T.ID == x.S.ID)
.Select(x => new { first = x.CFS.FirstName, status = x.S.Name, topic = x.T.Name})
.GroupBy(x => x.topic)
.Select(x => new SelectedTopic { Topic = x.Key, Status = "pass", Person = x.Select(z => z.first).Distinct().ToList() })
.Dump();
}
Tested in LinqPad -- if you are not using this tool I suggest you do so.