I have a table where each JunctionlistID is repeated many times. there is a JunctionlistID in front of each id in each row.
I want to select entire row for each JunctionlistID where ID is latest. There are total 5 columns in this table i want all columns to get selected when i select that row.
ID | MonitoringString| JunctionListId | area_id| CompanyProfileId
1 | 1006410001D0 | 267 | 910064 | 7
2 | 1206420001D0 | 268 | 910065 | 7
3 | 1306440001D0 | 267 | 910064 | 7
4 | 1506450001D0 | 268 | 910065 | 7
5 | 1606470001D0 | 267 | 910064 | 7
6 | 1806480001D0 | 268 | 910065 | 7
7 | 1006420001D0 | 267 | 910064 | 7
8 | 1006470001D0 | 268 | 910065 | 7
9 | 1006490001D0 | 267 | 910064 | 7
10 | 1006430001D0 | 268 | 910065 | 7
11 | 1006460001D0 | 285 | 910066 | 8
12 | 1006438001D0 | 268 | 910067 | 8
The Answer should be
ID | MonitoringString| JunctionListId | area_id| CompanyProfileId
9 | 1006490001D0 | 267 | 910064 | 7
10 | 1006430001D0 | 268 | 910065 | 7
I try the query as below -
Select ID,MonitoringString,JunctionListId,area_id,CompanyProfileId from tblMonitoring where CompanyProfileId=7
I need the query same as well in linq and SQL both, If anybody know please give me the proper solution.
Thanks
If I understand correctly, you just want the last records for each company and junction id, based on the id. You can use row_number():
Select m.*
from (select m.*,
row_number() over (partition by CompanyProfileId, JunctionListId order by id desc) as seqnum
from tblMonitoring m
) m
where CompanyProfileId = 7 and seqnum = 1;
https://dotnetfiddle.net/oiRkzO
using System;
using System.Data.Entity;
using System.Linq;
using System.Collections.Generic;
public class Program
{
public static void Main()
{
List<Item> items = new List<Item>()
{
new Item() { ID = 1, MonitoringString = "1006410001D0", JunctionListId = 267, area_id = 910064 , CompanyProfileId = 7},
new Item() { ID = 2, MonitoringString = "1206420001D0", JunctionListId = 268, area_id = 910065 , CompanyProfileId = 7},
new Item() { ID = 3, MonitoringString = "1306440001D0", JunctionListId = 267, area_id = 910064 , CompanyProfileId = 7},
new Item() { ID = 4, MonitoringString = "1506450001D0", JunctionListId = 268, area_id = 910065 , CompanyProfileId = 7},
new Item() { ID = 5, MonitoringString = "1606470001D0", JunctionListId = 267, area_id = 910064 , CompanyProfileId = 7},
new Item() { ID = 6, MonitoringString = "1806480001D0", JunctionListId = 268, area_id = 910065 , CompanyProfileId = 7},
new Item() { ID = 7, MonitoringString = "1006420001D0", JunctionListId = 267, area_id = 910064 , CompanyProfileId = 7},
new Item() { ID = 8, MonitoringString = "1006470001D0", JunctionListId = 268, area_id = 910065 , CompanyProfileId = 7},
new Item() { ID = 9, MonitoringString = "1006490001D0", JunctionListId = 267, area_id = 910064 , CompanyProfileId = 7},
new Item() { ID = 10, MonitoringString = "1006430001D0", JunctionListId = 268, area_id = 910065 , CompanyProfileId = 7},
new Item() { ID = 11, MonitoringString = "1006460001D0", JunctionListId = 285, area_id = 910066 , CompanyProfileId = 8},
new Item() { ID = 12, MonitoringString = "1006438001D0", JunctionListId = 268, area_id = 910067 , CompanyProfileId = 8},
};
var result = items.GroupBy(item => item.JunctionListId).Select(g => g.FirstOrDefault(gx => gx.ID == g.Max(x => x.ID))).ToList();
var resultCmp7 = items.Where(item => item.CompanyProfileId == 7).GroupBy(item => item.JunctionListId).Select(g => g.FirstOrDefault(gx => gx.ID == g.Max(x => x.ID))).ToList();
foreach (var item in result)
{
Console.WriteLine(string.Format("{0},{1},{2},{3}",item.ID, item.MonitoringString, item.JunctionListId,item.area_id, item.CompanyProfileId));
}
Console.WriteLine();
foreach (var item in resultCmp7)
{
Console.WriteLine(string.Format("{0},{1},{2},{3}",item.ID, item.MonitoringString, item.JunctionListId,item.area_id, item.CompanyProfileId));
}
Console.ReadLine();
}
class Item
{
public int ID { get; set; }
public string MonitoringString { get; set; }
public int JunctionListId { get; set; }
public int area_id { get; set; }
public int CompanyProfileId { get; set; }
}
}
For linq, you could do the following. (Looks like you also want to filter by companyprofileid)
var result = items.Where(x=>x.CompanyProfileId==7)
.GroupBy(x=>x.JunctionListId)
.Select(x=>x.ToList()
.OrderByDescending(c=>c.ID)
.ThenBy(c=>c.JunctionListId)
.First());
Select MAX(ID) ID,
Max(MonitoringString) MonitoringString,
Max(JunctionListID) JunctionListID,
Max(area_id) area_id,
Max(CompanyProfileId) CompanyProfileId
from MonitorsList
where CompanyProfileId = 7
Group by JunctionListID
Try this one,
SELECT COUNT(ID), MonitoringString, JunctionListId, are_id, CompanyProfileId FROM tblMonitoring WHERE CompanyProfileID = '7' GROUP BY CompanyProfileId;
Related
I am having issues with my nested foreach loop. I'm trying to populate data from by database to my list with information about car information (company, different car models). My issue has to do with my inner loop, and not being able to continue populating my list.
The results that I'm expecting is this:
"CompanyId": 1,
"CompanyName": "Toyota"
"ParentVehicleId": 2,
"ParentVehicleName": "Camry",
"ChildVehicleId": 4,
"ChildVehicleName":"Camry/Scepter"
"CompanyId": 1,
"CompanyName": "Toyota"
"ParentVehicleId": 4,
"ParentVehicleName": "Crown"
"ChildVehicleId": 0,
"ChildVehicleName":"N/A"
"CompanyId": 12,
"CompanyName": "Hyundai"
"ParentVehicleId": 13,
"ParentVehicleName": "Accent",
"ChildVehicleId": 0,
"ChildVehicleName":"N/A"
etc...
But what I'm actually getting is only these two:
"CompanyId": 1,
"CompanyName": "Toyota"
"ParentVehicleId": 2,
"ParentVehicleName": "Camry",
"ChildVehicleId": 3,
"ChildVehicleName":"Camry/Vista"
"CompanyId": 1,
"CompanyName": "Toyota"
"ParentVehicleId": 2,
"ParentVehicleName": "Camry",
"ChildVehicleId": 4,
"ChildVehicleName":"Camry/Scepter"
This is a snippet of my db table:
Vehicle Table
|----------------------------------------------|
| VehicleId | ManufactId | BrandName |
|----------------------------------------------|
| 1 | 1 | Toyota |
|----------------------------------------------|
| 2 | 1 | Camry |
|----------------------------------------------|
| 3 | 2 | Camry/Vista |
|----------------------------------------------|
| 4 | 2 | Camry/Scepter |
|----------------------------------------------|
| 5 | 4 | Crown |
|----------------------------------------------|
| 6 | 5 | Supra |
|----------------------------------------------|
C# code
public List<VehicleListModel>> VehicleMethod()
{
List<VehicleListModel> vehicleList = new List<VehicleListModel>();
foreach (var item in companyInfo)
{
var parentInfo = _context.VehicleTable.Where(y => item.VehicleId == y.ManufactId).ToList();
foreach (var item2 in parentInfo)
{
var childInfo = _context.VehicleTable.Where(y => item2.VehicleId == y.ManufactId).ToList();
foreach (var item3 in childInfo)
{
VehicleListModel vehList = new VehicleListModel();
//if ChildVehicleId does not exist, 0 & N/A are
//returned
vehList.CompanyId = item.VehicleId;
vehList.CompanyName = item?.BrandName ?? "N/A";
vehicleList.Add(vehList);
}
}
}
return vehicleList;
}
The problem is basically how your data is connected.
Let's take Toyota:
|----------------------------------------------|----------------|
| VehicleId | ManufactId | BrandId | BrandName |
|----------------------------------------------|----------------|
| 1 | null | 1 | Toyota |
|----------------------------------------------|----------------|
| 2 | 1 | 1 | Camry |
|----------------------------------------------|----------------|
| 3 | 2 | 1 | Camry/Vista |
|----------------------------------------------|----------------|
| 4 | 2 | 1 | Camry/Scepter |
As you can see, the model Camry is the relationship between the versions and the company.
When VehicleId is 2 (from Camry) you look for records where ManufactId is 2 (Vista and Scepter).
For Nissan instead:
|----------------------------------------------|----------------|
| VehicleId | ManufactId | BrandId | BrandName |
|----------------------------------------------|----------------|
| 9 | null | 9 | Nissan |
|----------------------------------------------|----------------|
| 10 | 9 | 9 | Datsun |
|----------------------------------------------|----------------|
| 11 | 9 | 9 | Datsun 13T |
Datsun doesn't have childs (no record have ManufactId equal to 10). Update Datsun 13 T record to ManufactId 10 to see it.
The same goes for the rest.
Moreover, because you hydrate the objects of the list inside the innermost foreach loop (and you never reach that code) you don't even get the empty objects.
If the data is wrong and you can't do anything about it, one possible way to handle these cases is to generate objects with the available info:
....
List<VehicleListModel> vehicleList = new List<VehicleListModel>();
var companies = _context.Where(x => x.ManufactId == null).ToList();
foreach (var company in companies)
{
var models = _context.Where(y => company.VehicleId == y.ManufactId).ToList();
if (models.Any())
{
foreach (var model in models)
{
var versions = _context.Where(y => model.VehicleId == y.ManufactId).ToList();
if (versions.Any())
{
foreach (var version in versions)
{
VehicleListModel vehList = new VehicleListModel();
vehList.CompanyId = company.VehicleId;
vehList.CompanyName = company?.BrandName ?? "N/A";
vehList.ParentVehicleId = model?.VehicleId ?? 0;
vehList.ParentVehicleName = model?.BrandName ?? "N/A";
vehList.ChildVehicleId = version?.VehicleId ?? 0;
vehList.ChildVehicleName = version?.BrandName ?? "N/A";
vehicleList.Add(vehList);
}
}
else
{
VehicleListModel vehList = new VehicleListModel();
vehList.CompanyId = company.VehicleId;
vehList.CompanyName = company.BrandName;
vehList.ParentVehicleId = model.VehicleId;
vehList.ParentVehicleName = model.BrandName;
vehList.ChildVehicleId = 0;
vehList.ChildVehicleName = "N/A";
vehicleList.Add(vehList);
}
}
}
else
{
VehicleListModel vehList = new VehicleListModel();
vehList.CompanyId = company.VehicleId;
vehList.CompanyName = company.BrandName;
vehList.ParentVehicleId = 0;
vehList.ParentVehicleName = "N/A";
vehList.ChildVehicleId = 0;
vehList.ChildVehicleName = "N/A";
vehicleList.Add(vehList);
}
}
....
Also, as #Yair suggested, you need to change Crown to ManufactId = 1
You are overriding the vehList instance in each iteration. Instead, you should move its initialization to the inner most loop, so a new instance is added to the list in each iteration:
foreach (var item in companyInfo)
{
var parentInfo = _context.VehicleTable.Where(y => item.VehicleId == y.ManufactId).ToList();
foreach (var item2 in parentInfo)
{
// This should be removed from the code:
// VehicleListModel vehList = new VehicleListModel();
var childInfo = _context.VehicleTable.Where(y => item2.VehicleId == y.ManufactId).ToList();
foreach (var item3 in childInfo)
{
// Instead, it's initialized here:
VehicleListModel vehList = new VehicleListModel();
//if ChildVehicleId does not exist, 0 & N/A are
//returned
vehList.CompanyId = item.VehicleId;
vehList.CompanyName = item?.BrandName ?? "N/A";
vehList.ParentVehicleId = item2?.VehicleId ?? 0;
vehList.ParentVehicleName = item2?.BrandName ?? "N/A";
vehList.ChildVehicleId = item3?.VehicleId ?? 0;
vehList.ChildVehicleName = item3?.BrandName ?? "N/A";
vehicleList.Add(vehList);
}
}
}
This is my code:
public class Photos
{
public long PhotoLabel { get; set; }
public int UserID { get; set; }
}
List<Photos> photolist = new List<Photos>();
var result1 = photolist.OrderByDescending(p => p.PhotoLabel).ThenBy(r => r.UserID).ToList();
If I display the contents now, this is what I get (First sorted in descending order of PhotoLabel and then sorted by UserID:
|------|---------------------|---------------------|
| Row | UserID | PhotoLabel |
|----------------------------|---------------------|
| 1 | 92 | 20180729181046 |
|----------------------------|---------------------|
| 2 | 92 | 20180729181041 |
|----------------------------|---------------------|
| 3 | 92 | 20180729181037 |
|----------------------------|---------------------|
| 4 | 88 | 20180729174415 |
|----------------------------|---------------------|
| 5 | 88 | 20180729174405 |
|----------------------------|---------------------|
| 6 | 04 | 20180729174358 |
|----------------------------|---------------------|
| 7 | 1 | 20170924183847 |
|----------------------------|---------------------|
| 8 | 1 | 20170921231422 |
|----------------------------|---------------------|
| 9 | 1 | 20170920194624 |
|----------------------------|---------------------|
| 10 | 32 | 20170820114728 |
|----------------------------|---------------------|
| 11 | 32 | 20170820114725 |
|----------------------------|---------------------|
| 12 | 32 | 20170820114421 |
|----------------------------|---------------------|
| 13 | 32 | 20170820114416 |
|----------------------------|---------------------|
| 14 | 1 | 20170225151023 |
|----------------------------|---------------------|
| 15 | 1 | 20170225151000 |
|----------------------------|---------------------|
| 16 | 1 | 20170225150957 |
|----------------------------|---------------------|
From the sorted table above, this is what I want to achieve:
Display groups of UserIDs and PhotoLabels where UserIDs appear 3 or more times in one group (eg: rows 4 and 5 where UserID=88 and row 6 where UserID=04 should be eliminated since the UserID=88 appears just twice in the group and UserID=04 appears only once in the group).
Display only the top most group of UserIDs and exclude any repeating UserIDs (eg: rows 7,8 and 9 displays the UserID=1 group. Don't display any other UserID=1 group such as rows 14,15 and 16. )
The expected result from query should be:
|------|---------------------|---------------------|
| Row | UserID | PhotoLabel |
|----------------------------|---------------------|
| 1 | 92 | 20180729181046 |
|----------------------------|---------------------|
| 2 | 92 | 20180729181041 |
|----------------------------|---------------------|
| 3 | 92 | 20180729181037 |
|----------------------------|---------------------|
| 7 | 1 | 20170924183847 |
|----------------------------|---------------------|
| 8 | 1 | 20170921231422 |
|----------------------------|---------------------|
| 9 | 1 | 20170920194624 |
|----------------------------|---------------------|
| 10 | 32 | 20170820114728 |
|----------------------------|---------------------|
| 11 | 32 | 20170820114725 |
|----------------------------|---------------------|
| 12 | 32 | 20170820114421 |
|----------------------------|---------------------|
| 13 | 32 | 20170820114416 |
|----------------------------|---------------------|
Thank you so much in in advance! :-)
If I am not misunderstood the requirement, below function properly works (but it shouldn't the most efficient solution)
protected List<AnObject> aFunction(List<AnObject> sortedList)
{
//Display groups of UserIDs and PhotoLabels where UserIDs appear 3 or more times in one group (eg: rows 4 and 5 where UserID = 88 and row 6 where UserID = 04 should be eliminated since the UserID = 88 appears just twice in the group and UserID = 04 appears only once in the group).
//Display only the top most group of UserIDs and exclude any repeating UserIDs(eg: rows 7, 8 and 9 displays the UserID = 1 group.Don't display any other UserID=1 group such as rows 14,15 and 16.
int pivot = -1;
int cnt = 0;
List<AnObject> masterList = new List<AnObject>();
List<AnObject> subList = new List<AnObject>();
//List<int> Excluded = new List<int>();
foreach (AnObject r in sortedList)
{
if (pivot != r.UserID)
{
if (cnt > 2)
{
masterList.AddRange(subList);
//Excluded.Add(pivot);
}
subList.Clear();
pivot = -1;
cnt = 0;
//if (!Excluded.Contains(r.UserID))
if (!masterList.Any(x => x.UserID == r.UserID))
{
pivot = r.UserID;
}
}
subList.Add(r);
cnt++;
}
return masterList;
}
To call it for testing
protected class AnObject
{
public AnObject(int uid, string photolabel)
{
this.UserID = uid;
this.PhotoLabel = photolabel;
}
public int UserID { get; set; }
public string PhotoLabel { get; set; }
}
protected void Execute()
{
List<AnObject> sortedList = new List<AnObject>();
sortedList.Add(new AnObject(92, "anystring"));
sortedList.Add(new AnObject(92, "anystring"));
sortedList.Add(new AnObject(92, "anystring"));
sortedList.Add(new AnObject(88, "anystring"));
sortedList.Add(new AnObject(88, "anystring"));
sortedList.Add(new AnObject(4, "anystring"));
sortedList.Add(new AnObject(1, "anystringfirst"));
sortedList.Add(new AnObject(1, "anystringfirst"));
sortedList.Add(new AnObject(1, "anystringfirst"));
sortedList.Add(new AnObject(32, "anystring"));
sortedList.Add(new AnObject(32, "anystring"));
sortedList.Add(new AnObject(32, "anystring"));
sortedList.Add(new AnObject(32, "anystring"));
sortedList.Add(new AnObject(1, "anystringafter"));
sortedList.Add(new AnObject(1, "anystringafter"));
sortedList.Add(new AnObject(1, "anystringafter"));
List<AnObject> bb = aFunction(sortedList);
}
Please wait! This is not the final answer! a little bit further modification is needed! modification is underway.
List<Photos> photolist = new List<Photos>()
{
new Photos() {UserID = 92, PhotoLabel = 20180729181046},
new Photos() {UserID = 92, PhotoLabel = 20180729181041},
new Photos() {UserID = 92, PhotoLabel = 20180729181037},
new Photos() {UserID = 88, PhotoLabel = 20180729174415},
new Photos() {UserID = 88, PhotoLabel = 20180729174405},
new Photos() {UserID = 04, PhotoLabel = 20180729174358},
new Photos() {UserID = 1, PhotoLabel = 20170924183847},
new Photos() {UserID = 1, PhotoLabel = 20170921231422},
new Photos() {UserID = 1, PhotoLabel = 20170920194624},
new Photos() {UserID = 32, PhotoLabel = 20170820114728},
new Photos() {UserID = 32, PhotoLabel = 20170820114725},
new Photos() {UserID = 32, PhotoLabel = 20170820114421},
new Photos() {UserID = 32, PhotoLabel = 20170820114416},
new Photos() {UserID = 1, PhotoLabel = 20170225151023},
new Photos() {UserID = 1, PhotoLabel = 20170225151000},
};
var photolist2 = photolist.GroupBy(g => g.UserID)
.Select(p => new
{
UserId = p.Key,
Count = p.Count()
})
.ToList();
var filteredPhotoList = photolist
.Join(photolist2,
photo => photo.UserID,
photo2 => photo2.UserId,
(photo, photo2) => new {UserId = photo.UserID, PhotoLabel =
photo.PhotoLabel, Count = photo2.Count})
.Where(p => p.Count > 2).Select(p => new
{
p.UserId, p.PhotoLabel
}).OrderByDescending(p => p.PhotoLabel).ThenBy(p => p.UserId).ToList();
Thank you all for your help. SKLTFZ's and TanvirArjel's answers were close but didn't achieve the expected results. I realized that you cannot achieve everything described above in Linq, so this is what I came up with and it achieves everything listed above:
PS: I renamed var result1 to ordered_photolist
List<Photos> ordered_photolist = photolist.OrderByDescending(p => p.PhotoLabel).ThenBy(r => r.UserID).ToList();
List<Photos> temp_photolist = new List<Photos>();
List<Photos> final_photolist = new List<Photos>();
int UserID = -1;
int UserIDCount = 0;
foreach (Photos p in ordered_photolist)
{
if (UserID == -1)
{
UserID = p.UserID;
temp_photolist.Add(p);
UserIDCount++;
}
else
{
if ( UserID == p.UserID )
{
temp_photolist.Add(p);
UserIDCount++;
}
else
{
if ( UserIDCount >= 3 )
{
// add temp_photolist to final list
int index = final_photolist.FindIndex(item => item.UserID == UserID);
if (index == -1)
{
// element does not exists, do what you need
final_photolist.AddRange(temp_photolist);
}
temp_photolist.Clear();
temp_photolist.Add(p);
UserIDCount = 1;
UserID = p.UserID;
}
else
{
temp_photolist.Clear();
UserIDCount = 0;
UserID = -1;
}
}
}
}
I currently have the following classes:
public class NavigationItem
{
public int ID { get; set; }
public string Title { get; set; }
public int ParentID { get; set; }
public List<NavigationItem> Children { get; set; }
}
public class FlatItem
{
public int ID { get; set; }
public string Title { get; set; }
public int ParentID { get; set; }
}
I have a sample data as follows:
+====+============+==========+
| ID | Title | ParentID |
+====+============+==========+
| 1 | Google | |
+----+------------+----------+
| 2 | Microsoft | |
+----+------------+----------+
| 3 | Oracle | |
+----+------------+----------+
| 4 | Gmail | 1 |
+----+------------+----------+
| 5 | Sheets | 1 |
+----+------------+----------+
| 6 | Adsense | 1 |
+----+------------+----------+
| 7 | Azure | 2 |
+----+------------+----------+
| 8 | SharePoint | 2 |
+----+------------+----------+
| 9 | Office | 2 |
+----+------------+----------+
| 10 | Java | 3 |
+----+------------+----------+
| 11 | Word | 9 |
+----+------------+----------+
| 12 | Excel | 9 |
+----+------------+----------+
| 13 | PowerPoint | 9 |
+----+------------+----------+
I already have the code to pull all the information from the sample data above and turn it into a List<FlatItem> object.
What's the best approach so that I can have a List<NavigationItem> object which will look like something below:
Google
Gmail
Sheets
AdSense
Microsoft
Azure
SharePoint
Office
Word
Excel
PowerPoint
Oracle
Java
I'm thinking of creating a recursive method to loop through my List<FlatItem> then structure it in a way to be a nested list of NavigationItem.
No need for recursion. You could use LINQ to build the structure easily:
List<FlatItem> flatItems = ...;
var navigationItems = flatItems.Select(
i => new NavigationItem { ID = i.ID, Title = i.Title, ParentID = i.ParentID }
).ToList();
foreach (var i in navigationItems)
i.Children = navigationItems.Where(n => n.ParentID == i.ID).ToList();
// get Google, Microsoft, Oracle items
var rootNavigationItems = navigationItems.Where(n => n.ParentID == 0);
Try this:
List<FlatItem> source = new List<UserQuery.FlatItem>()
{
new FlatItem() { ID = 1, Title = "Google", ParentID = null },
new FlatItem() { ID = 2, Title = "Microsoft", ParentID = null },
new FlatItem() { ID = 3, Title = "Oracle", ParentID = null },
new FlatItem() { ID = 4, Title = "Gmail", ParentID = 1 },
new FlatItem() { ID = 5, Title = "Sheets", ParentID = 1 },
new FlatItem() { ID = 6, Title = "Adsense", ParentID = 1 },
new FlatItem() { ID = 7, Title = "Azure", ParentID = 2 },
new FlatItem() { ID = 8, Title = "SharePoint", ParentID = 2 },
new FlatItem() { ID = 9, Title = "Office", ParentID = 2 },
new FlatItem() { ID = 10, Title = "Java", ParentID = 3 },
new FlatItem() { ID = 11, Title = "Word", ParentID = 9 },
new FlatItem() { ID = 12, Title = "Excel", ParentID = 9 },
new FlatItem() { ID = 13, Title = "PowerPoint", ParentID = 9 },
};
var lookup = source.ToLookup(x => x.ParentID);
Func<int?, List<NavigationItem>> build = null;
build = pid =>
lookup[pid]
.Select(x => new NavigationItem()
{
ID = x.ID,
Title = x.Title,
ParentID = x.ParentID,
Children = build(x.ID)
})
.ToList();
To start the process call build(null). That gives me this:
This does assume that the ParentId property is a int? - which your data table does suggest.
If you are ok with using recursion, you can create a function like this:
public List<NavigationItem> ChildrenOf(List<FlatItem> flatItems, int parentId)
{
var childrenFlatItems = flatItems.Where(i => i.ParentID == parentId);
return childrenFlatItems.Select(i => new NavigationItem {
ID = i.ID,
Title = i.Title,
ParentID = i.ParentID,
Children = ChildrenOf(flatItems, i.ID)})
.ToList();
}
Then, assuming that your root items have a parent id of 0 (since you aren't using nullable types), you generate the full list with:
ChildrenOf(flatsItems, 0)
Untested, however you could try this, should be fairly fast as well
var list = new List<FlatItem>();
var result = new List<NavigationItem>();
// just a helper to remember ids
var dict = new Dictionary<int, NavigationItem>();
foreach (var item in list)
{
var nav = new NavigationItem()
{
ID = item.ID,
ParentID = item.ParentID,
Title = item.Title,
Children = new List<NavigationItem>()
};
if (!dict.ContainsKey(nav.ParentID))
result.Add(nav);
else
dict[nav.ParentID].Children.Add(nav);
dict.Add(item.ID, nav);
}
no recursive, just GroupBy.
List<NavigationItem> list = ... // map from List<FlatItem>
// and init Children = new List<NavigationItem>();
var groups = list.GroupBy(x => x.ParentID).ToList();
foreach (var g in groups)
{
var items = list.Find(x => x.ID == g.Key);
if (items != null)
items.Children = g.ToList();
}
// tops is [Google, Microsoft, Oracle]
var tops = list.Where(x => x.ParentID == null).ToList();
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
I want to retrieve all records of manufacturer in LINQ using a many-to-many join.
Lets consider
Table 'Item':
id | name
----------
1 | A
---------
2 | B
--------
3 | C
--------
Table 'Manufacturer':
ManufactuerId | Name
-------------------
1 | XYZ
-------------------
2 | ABC
--------------------
3 | ZZZ
----------------------
Table 'ManufacturerItem':
ManufacturerItemID | ManufacturerId | ItemId
-------------------------------------------
1 | 1 | 1
-------------------------------------------
2 | 1 | 2
-------------------------------------------
3 | 2 | 1
------------------------------------------
4 | 3 | 2
------------------------------------------
5 | 1 | 3
------------------------------------------
I would like to fetch the records of a manufacturer(s) who has all the items that I have supplied in.
So, given an input of {A, B} I would like to get an output of XYZ Manufacturer.
var tableItems = new[] {
new { Id = 1, Name = "A" },
new { Id = 2, Name = "B" },
new { Id = 3, Name = "C" }
};
var tableManufacturer = new[] {
new { ManufacturerId = 1, Name = "XYZ" },
new { ManufacturerId = 2, Name = "ABC" },
new { ManufacturerId = 3, Name = "ZZZ" }
};
var tableManufacturerItem = new[]
{
new {ManufacturerItemID = 1, ManufacturerId = 1, ItemId = 1},
new {ManufacturerItemID = 2, ManufacturerId = 1, ItemId = 2},
new {ManufacturerItemID = 3, ManufacturerId = 2, ItemId = 1},
new {ManufacturerItemID = 4, ManufacturerId = 3, ItemId = 2},
new {ManufacturerItemID = 5, ManufacturerId = 1, ItemId = 3},
};
var itemsToSearch = new[] { "A", "B" };
var result = tableManufacturerItem
.GroupBy(x => x.ManufacturerId)
.Where(m => tableItems.Where(item => itemsToSearch.Contains(item.Name)).Select(x => x.Id)
.Except(m.Select(x => x.ItemId))
.Count() == 0)
.Select(x => tableManufacturer.First(m => m.ManufacturerId == x.Key))
.Select(m => m.Name)
.ToList();
This is my first time to hear about LINQ and I have no idea about it. Please be gentle on me.
I have this set of data.
+---------+--------+---------------+
| RadioID | NodeID | SourceRadioID |
+---------+--------+---------------+
| R0 | 1 | |
| R1 | 1 | |
| R2 | 1 | |
| R3 | 1 | |
| R4 | 1 | |
| R5 | 2 | |
| R6 | 2 | |
| R7 | 2 | R0 |
| R8 | 2 | |
| R9 | 2 | |
| R10 | 11 | |
| R11 | 11 | R9 |
| R12 | 11 | |
| R13 | 11 | |
+---------+--------+---------------+
What I need to do is to write a method that returns a list of NodeID. example,
List<int> dependentNode = GetChildNode(1); // int ParentNode
My expected results are NodeIDs: 2 and 11.
NodeID = 2 is included because there is a RadioID = R7 that is connected to RadioID = R0 which belongs to NodeID = 1.
NodeID = 11 is also included because RadioID = R11 is connected to Radio = R9 which belongs to NodeID = 2 (which is also connected to NodeID = 1).
I lookup this article but I always get StackOverFlowException
Rendering a hierarchy using LINQ
Here's the full code:
public class RadioEntity
{
public string RadioID { get; set; }
public int NodeID { get; set; }
public string SourceRadioID { get; set; }
}
public class SampleDemo
{
public void SampleMethod()
{
Func<int, int,List<int>> GetChildNode = null;
GetChildNode = (x, y) =>
{
return (from _x in GetRadio()
where (GetRadio().Where(i => i.NodeID == x).Select(i => i.RadioID)).Contains(_x.RadioID)
from _y in new[] { _x.NodeID }.Union(GetChildNode(_x.NodeID, y + 1))
select _y).ToList<int>();
};
var _res = GetChildNode(1, 0);
}
public List<RadioEntity> GetRadio()
{
List<RadioEntity> _returnVal = new List<RadioEntity>();
_returnVal.Add(new RadioEntity() { RadioID = "R0", NodeID = 1, SourceRadioID = "" });
_returnVal.Add(new RadioEntity() { RadioID = "R1", NodeID = 1, SourceRadioID = "" });
_returnVal.Add(new RadioEntity() { RadioID = "R2", NodeID = 1, SourceRadioID = "" });
_returnVal.Add(new RadioEntity() { RadioID = "R3", NodeID = 1, SourceRadioID = "" });
_returnVal.Add(new RadioEntity() { RadioID = "R4", NodeID = 1, SourceRadioID = "" });
_returnVal.Add(new RadioEntity() { RadioID = "R5", NodeID = 2, SourceRadioID = "" });
_returnVal.Add(new RadioEntity() { RadioID = "R6", NodeID = 2, SourceRadioID = "" });
_returnVal.Add(new RadioEntity() { RadioID = "R7", NodeID = 2, SourceRadioID = "R0" });
_returnVal.Add(new RadioEntity() { RadioID = "R8", NodeID = 2, SourceRadioID = "" });
_returnVal.Add(new RadioEntity() { RadioID = "R9", NodeID = 2, SourceRadioID = "" });
_returnVal.Add(new RadioEntity() { RadioID = "R10", NodeID = 11, SourceRadioID = "" });
_returnVal.Add(new RadioEntity() { RadioID = "R11", NodeID = 11, SourceRadioID = "R9" });
_returnVal.Add(new RadioEntity() { RadioID = "R12", NodeID = 11, SourceRadioID = "" });
_returnVal.Add(new RadioEntity() { RadioID = "R13", NodeID = 11, SourceRadioID = "" });
return _returnVal;
}
}
You can suggest if there is much better way to do it. Sorry Newbie here.
If you are newbie dont be too clever with recursion and lambdas.
public List<int> GetChildren(int id)
{
var nodes = GetRadio();
var parent = nodes.Single(n => n.NodeID == id);
var children = nodes.Where(n => n.SourceRadioID == parent.RadioID).Select(n => n.NodeID);
return children.Union(children.SelectMany(GetChildren)).ToList();
}
UPDATE 1
public List<int> GetChildren(int id)
{
IEnumerable<RadioEntity> parent = GetRadio().Where(x => x.NodeID == id);
IEnumerable<int> children = (
from r in GetRadio()
where parent.Select(x=>x.RadioID)
.Contains(r.SourceRadioID)
select r
).Select(n => n.NodeID);
return children.Union(children.SelectMany(GetChildren)).ToList();
}