列表<Object>到层次结构
List<Object> to hierarchy
我有一个 List<Data>
,其中数据是
public class Data
{
public string SchoolId {get; set;}
public string SchoolName {get; set;}
public string TeacherId {get; set;}
public string TeacherName {get; set;}
}
列表是扁平的:
SchoolId SchoolName TeacherId TeacherName
1 X 1 Mr X
1 X 2 Mrs Y
2 Y 3 Mr Z
2 Y 1 Mr X
所以基本上一个老师可以属于很多学校
如何将上面的平面列表转换为 List<School>
public class School
{
public School()
{
this.Teachers = new List<Teacher>();
}
public string SchoolId { get; set; }
public string SchoolName { get; set; }
public List<Teacher> Teachers {get; set;}
}
public class Teacher
{
public string TeacherId { get; set; }
public string TeacherName { get; set; }
}
如果这是 Linq to objects,则使用此代码
var result = list.GroupBy(x=>new {x.SchoolId, x.SchoolName})
.Select(x=>
{
var s = new School();
s.SchoolId = x.Key.SchoolId;
s.SchoolName = x.Key.SchoolName;
s.Teachers.AddRange(x.Select(
y => new Teacher
{
TeacherId = y.TeacherId,
TeacherName = y.TeacherName
}
));
return s;
});
请注意,即使 Teacher
具有相同的 Id
。
,以上代码将导致重复的 Teacher
实例
此方法的阶数为 O(n^2),并且不共享教师实例。
var schools = data
.GroupBy(x => x.SchoolId)
.Select(group => new School()
{
SchoolId = group.Key,
SchoolName = group.First().SchoolName,
Teachers = data.Where(x => x.SchoolId == group.Key)
.Select(x => new Teacher()
{
TeacherId = x.TeacherId,
TeacherName = x.TeacherName
})
.ToList()
})
.ToList();
如果你想分享教师的实例,那么你可以使用这个
var teachersById = data
.GroupBy(x => x.TeacherId)
.Select(group => new Teacher()
{
TeacherId = group.Key,
TeacherName = group.First().TeacherName
})
.ToDictionary(x => x.TeacherId);
var schools = data
.GroupBy(x => x.SchoolId)
.Select(group => new School()
{
SchoolId = group.Key,
SchoolName = group.First().SchoolName,
Teachers = teachersById
.Where(kv => data
.Where(x => x.SchoolId == group.Key)
.Select(x => x.TeacherId)
.Contains(kv.Key)
)
.Select(x => x.Value)
.ToList()
})
.ToList();
List<Data> dataList = new List<Data>();
IEnumerable<School> schools = from d in dataList
group d by new { SchoolId = d.SchoolId, SchoolName = d.SchoolName } into groupSchool
select new School { SchoolId = groupSchool.Key.SchoolId, SchoolName = groupSchool.Key.SchoolName, Teachers =new List<Teacher>(groupSchool.Select(x => new Teacher { TeacherId = x.TeacherId, TeacherName = x.TeacherName })) };
item.SchoolIdNote:它是伪代码(对于简短的代码,我使用带参数的构造函数而不是使用属性)
List<Data> data = //....;
Dictionary<string, Teacher> teachers = new Dictionary<string, Teacher>();
Dictionary<string, School> schools = new Dictionary<string, School>();
foreach (var item in data)
{
if (item.TeacherId not in teachers)
teachers.add(item.TeacherId, new Teacher(item.TeacherId, item.TeacherName));
}
foreach (var item in data)
{
if (item.SchoolId not in schools)
schools.add(item.SchoolId , item.SchoolName, new School(item.SchoolId , teachers[item.SchoolId]));
}
List<School> gen_schools = // get values from schools;
P.S。实际上你使用了错误的数据库表示法(你应该将教师和学校分开到两个不同的表中)。
我有一个 List<Data>
,其中数据是
public class Data
{
public string SchoolId {get; set;}
public string SchoolName {get; set;}
public string TeacherId {get; set;}
public string TeacherName {get; set;}
}
列表是扁平的:
SchoolId SchoolName TeacherId TeacherName
1 X 1 Mr X
1 X 2 Mrs Y
2 Y 3 Mr Z
2 Y 1 Mr X
所以基本上一个老师可以属于很多学校
如何将上面的平面列表转换为 List<School>
public class School
{
public School()
{
this.Teachers = new List<Teacher>();
}
public string SchoolId { get; set; }
public string SchoolName { get; set; }
public List<Teacher> Teachers {get; set;}
}
public class Teacher
{
public string TeacherId { get; set; }
public string TeacherName { get; set; }
}
如果这是 Linq to objects,则使用此代码
var result = list.GroupBy(x=>new {x.SchoolId, x.SchoolName})
.Select(x=>
{
var s = new School();
s.SchoolId = x.Key.SchoolId;
s.SchoolName = x.Key.SchoolName;
s.Teachers.AddRange(x.Select(
y => new Teacher
{
TeacherId = y.TeacherId,
TeacherName = y.TeacherName
}
));
return s;
});
请注意,即使 Teacher
具有相同的 Id
。
Teacher
实例
此方法的阶数为 O(n^2),并且不共享教师实例。
var schools = data
.GroupBy(x => x.SchoolId)
.Select(group => new School()
{
SchoolId = group.Key,
SchoolName = group.First().SchoolName,
Teachers = data.Where(x => x.SchoolId == group.Key)
.Select(x => new Teacher()
{
TeacherId = x.TeacherId,
TeacherName = x.TeacherName
})
.ToList()
})
.ToList();
如果你想分享教师的实例,那么你可以使用这个
var teachersById = data
.GroupBy(x => x.TeacherId)
.Select(group => new Teacher()
{
TeacherId = group.Key,
TeacherName = group.First().TeacherName
})
.ToDictionary(x => x.TeacherId);
var schools = data
.GroupBy(x => x.SchoolId)
.Select(group => new School()
{
SchoolId = group.Key,
SchoolName = group.First().SchoolName,
Teachers = teachersById
.Where(kv => data
.Where(x => x.SchoolId == group.Key)
.Select(x => x.TeacherId)
.Contains(kv.Key)
)
.Select(x => x.Value)
.ToList()
})
.ToList();
List<Data> dataList = new List<Data>();
IEnumerable<School> schools = from d in dataList
group d by new { SchoolId = d.SchoolId, SchoolName = d.SchoolName } into groupSchool
select new School { SchoolId = groupSchool.Key.SchoolId, SchoolName = groupSchool.Key.SchoolName, Teachers =new List<Teacher>(groupSchool.Select(x => new Teacher { TeacherId = x.TeacherId, TeacherName = x.TeacherName })) };
item.SchoolIdNote:它是伪代码(对于简短的代码,我使用带参数的构造函数而不是使用属性)
List<Data> data = //....;
Dictionary<string, Teacher> teachers = new Dictionary<string, Teacher>();
Dictionary<string, School> schools = new Dictionary<string, School>();
foreach (var item in data)
{
if (item.TeacherId not in teachers)
teachers.add(item.TeacherId, new Teacher(item.TeacherId, item.TeacherName));
}
foreach (var item in data)
{
if (item.SchoolId not in schools)
schools.add(item.SchoolId , item.SchoolName, new School(item.SchoolId , teachers[item.SchoolId]));
}
List<School> gen_schools = // get values from schools;
P.S。实际上你使用了错误的数据库表示法(你应该将教师和学校分开到两个不同的表中)。