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 :
Related
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);
I encountered a ridiculous problem using Linq into C# with my database included.
I tried so hard to sort by the name who got the higher rank of occurence.
Such as :
Toto : 1 occurence.
Titi : 3 occurences.
fonction.
consolewriteLine(the one who got the higher score of occurences )
So, it will be Titi.
But now in Linq, this is my code :
public static void AfficherLePrenomMasculinLePlusFrequentParmiLesElus()
{
using (var context = new electionEDM3())
{
var queryPrenomMasculin = from listedesprenomsM in context.Candidat
where listedesprenomsM.sexe == "M"
select listedesprenomsM;
var prenomMasculinTrouve = from prenommasculintrouve in queryPrenomMasculin
orderby prenommasculintrouve.prenom
group prenommasculintrouve by prenommasculintrouve.prenom into nombredeprenommasculintrouve
select new
{
prenom = nombredeprenommasculintrouve.Key,
count = nombredeprenommasculintrouve.Count()
};
foreach (var PrenomMPlusSouventPresent in prenomMasculinTrouve)
{
int i = 0;
int BestPrenomM = 0;
string MeilleurPrenomMasculin = "";
if ( PrenomMPlusSouventPresent.count > BestPrenomM)
{
BestPrenomM = PrenomMPlusSouventPresent.count;
MeilleurPrenomMasculin = PrenomMPlusSouventPresent.prenom;
BestPrenomM++;
}
Console.WriteLine(BestPrenomM);
}
}
}
As a result, i only got all the occurences of the " Prenom ". And not the one who got the higher score.
What should i do ?
Thank for your answers !
you are ordering using prenommasculintrouve.prenom and after that you are grouping, that is useless. You should order the result of the grouped data, using the count property of your anonymous type (prenom, count properties)
Your order by in your initial grouping is unnecessary.
Get the grouping first, then order by count descending, and take the first value. That should be the result you need.
I will give you a simple example
public class Person
{
public string Sex { get; set; }
public string name { get; set; }
}
private static void Linq2()
{
var namesList = new List<Person>();
namesList.Add(new Person() { Sex = "M", name = "Jonh" });
namesList.Add(new Person() { Sex = "M", name = "James" });
namesList.Add(new Person() { Sex = "F", name = "Maria" });
namesList.Add(new Person() { Sex = "F", name = "Cindy" });
namesList.Add(new Person() { Sex = "M", name = "Jim" });
namesList.Add(new Person() { Sex = "F", name = "Helen" });
namesList.Add(new Person() { Sex = "M", name = "Jonh" });
namesList.Add(new Person() { Sex = "F", name = "Maria" });
namesList.Add(new Person() { Sex = "F", name = "Cindy" });
namesList.Add(new Person() { Sex = "M", name = "Jonh" });
var grouped = from personItem in namesList
group personItem by personItem.name into personGroup
select new
{
name = personGroup.Key,
count = personGroup.Count()
};
// here you order your list Descending in order the name
// with the most Ocurrance will be on the top and select the First
var nameMaxOcurrance = grouped.OrderByDescending(x => x.count).First().name;
var maxOcurrance = grouped.Max(x => x.count);
Console.WriteLine("Name with Max Ocurrances:" + nameMaxOcurrance);
Console.WriteLine("Max Ocurrances:" + maxOcurrance);
}
In your case
var nameMaxOcurrance = prenomMasculinTrouve.OrderByDescending(x => x.count).First().prenom;
var maxOcurrances = prenomMasculinTrouve.Max(x => x.count);
I have an object which has a variable length list of items (incomingList in code example) and a list of people which each have a list of items. I want to return only those people that have all the items in the incomingList.
So looking at the example, I only want person 1 and 3 returned.
The people are in a database and I want to retrieve as little data as possible so I am trying to work out what the linq query needs to be to achieve this? If I knew the length of the incomingList was always going to be the same I could do "...Any(..) && ...Any(...) &&" etc - but the length will vary.
void Main()
{
var incomingList = new IncomingItem();
var matchItem1 = new MatchItem { ItemType = "objectId", ItemValue = "60" };
var matchItem2 = new MatchItem { ItemType = "area", ItemValue = "CU" };
incomingList.MatchList = new List<MatchItem>();
incomingList.MatchList.Add(matchItem1);
incomingList.MatchList.Add(matchItem2);
var people = new List<Person>();
var person1 = new Person { Id = 1 };
person1.ListOfItems = new List<Item>();
person1.ListOfItems.Add(new Item { ItemType = "objectId", ItemValue = "60" });
person1.ListOfItems.Add(new Item { ItemType = "objectId", ItemValue = "1" });
person1.ListOfItems.Add(new Item { ItemType = "objectId", ItemValue = "30" });
person1.ListOfItems.Add(new Item { ItemType = "area", ItemValue = "CO" });
person1.ListOfItems.Add(new Item { ItemType = "area", ItemValue = "CU" });
people.Add(person1);
var person2 = new Person { Id = 2 };
person2.ListOfItems = new List<Item>();
person2.ListOfItems.Add(new Item { ItemType = "objectId", ItemValue = "60" });
people.Add(person2);
var person3 = new Person { Id = 3 };
person3.ListOfItems = new List<Item>();
person3.ListOfItems.Add(new Item { ItemType = "objectId", ItemValue = "60" });
person3.ListOfItems.Add(new Item { ItemType = "area", ItemValue = "CU" });
people.Add(person3);
var person4 = new Person { Id = 4 };
person4.ListOfItems = new List<Item>();
person4.ListOfItems.Add(new Item { ItemType = "objectId", ItemValue = "12" });
people.Add(person4);
}
public class IncomingItem
{
public IList<MatchItem> MatchList { get; set; }
}
public class MatchItem
{
public List<object> SomeMoreInformation { get; set; }
public string ItemType { get; set; }
public string ItemValue { get; set; }
}
public class Person
{
public int Id { get; set; }
public IList<Item> ListOfItems { get; set; }
}
public class Item
{
public int Id { get; set; }
public int PersonId { get; set; }
public string ItemType { get; set; }
public string ItemValue { get; set; }
}
This returns all people that have all items of incomingList in their ListOfItems:
var result = people.Where(p => incomingList.MatchList
.All(l => p.ListOfItems.Select(loi => new { loi.ItemType, loi.ItemValue })
.Contains(new { l.ItemType, l.ItemValue }) ));
Anonymous types should have properties with equal names and types to resolve to "equal", which condition is met in this case.
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
I have a list of Products that came from the database and from this list, I used LINQ and return as a List of Phone class.
List<Product> products = new List<Product>
{
new Product { ID = 1, Name = "Alcohol", Expired = false },
new Product { ID = 2, Name = "Phone", Expired = false },
new Product { ID = 2, Name = "Phone", Expired = false },
new Product { ID = 3, Name = "Computer", Expired = false },
new Product { ID = 4, Name = "Chair", Expired = false },
};
var results = from i in products.Where(o => o.Name == "Phone")
select new Phones
{
ID = i.ID,
Phone = i.Name,
isChild = i.Expired
};
//Update the isChild property
foreach (var item in results)
{
item.isChild = true;
}
public class Phones
{
public int ID { get; set; }
public string Phone { get; set; }
public bool isChild { get; set; }
}
I used to update the list of Phones using foreach loop. But the problem is when I checked the results variable it doesn't update the said items.
Thats because of deferred execution of the IEnumerable. Try casting your results ToList to immediate execute that query:
var results = (from i in products.Where(o => o.Name == "Phone")
select new Phones
{
ID = i.ID,
Phone = i.Name,
isChild = i.Expired
}).ToList();
If you won't - it would requery the products every time and you will work with a new set of Phones.