[英]Group records stored in one-dimensional array using LINQ
I have a situation, where I get data from the database in such a way, that everything is stored in one-dimensional array. 我有一种情况,我以这种方式从数据库中获取数据,所有内容都存储在一维数组中。
For example: 例如:
User table: UserId, Name
Group table: GroupId, Name
UserGroup table: UserId, GroupId
As a result of joining these tables I obtain array of the following form: 连接这些表的结果是,我获得了以下形式的数组:
result[0] = "1" // user id
result[1] = "John Doe" // user name
result[2] = "121" // group id
result[3] = "SomeGroup" // group name
result[4] = "1" // user id
result[5] = "John Doe" // user name
result[6] = "2135" // group id
result[7] = "SomeOtherGroup" // group name
I know it's not a good solution of keeping data, but these data are coming to me from some other piece of code which I am not allowed to change, so I have to deal with it. 我知道这不是保存数据的好方法,但是这些数据是从其他一些我无法更改的代码中获取的,因此我必须加以处理。
My questions are: 我的问题是:
Pure linq Expression : 纯linq表达式:
int i = 0;
var objects = result.GroupBy(x => Math.Floor(i++ / 4.0))
.Select(g => new { id =g.ElementAt(0), name = g.ElementAt(1), gId= g.ElementAt(2), group = g.ElementAt(3)})
.GroupBy(x=>new {x.id, x.name}, x=>new {x.gId, x.group})
.Select(y=>new {y.Key, groups = y.ToList()});
GroupBy
I group results in 4 elements subsets using a floor and a temporary variable. GroupBy
我使用下限和临时变量对4个元素子集进行分组。 Select
put the resulting arrays in an anonymous type for better usability in the next steps. Select
将结果数组放入匿名类型,以在下一步中提供更好的可用性。 GroupBy
is used to group the entries by Employee. GroupBy
用于按Employee对条目进行分组。 The Key will be the employee and the values will be the corresponding Groups. Select
is used to put the GroupBy
result in a better shape. Select
来使GroupBy
结果具有更好的形状。 I choose to put the result in an other anonymous type but You could instantiate you custom objects here and put the values in the right fields using curly brace constructor. If your logic depends on indexes LINQ is is rarely the right tool. 如果您的逻辑依赖于索引,则LINQ几乎不是正确的工具。 It results in less readable, maintainable, efficient and robust code than with plain loops.
与普通循环相比,它导致可读性,可维护性,效率和鲁棒性较低的代码。
I would use something like following to create two dictionaries representing the many to many relation. 我将使用类似以下内容的方法来创建两个表示多对多关系的字典。 Note the
for
-loop which increments by 4 on every iteration since that seems to be the user-group-"package": 请注意
for
-loop,它在每次迭代时增加4,因为这似乎是user-group-“ package”:
var userIdGroups = new Dictionary<int, HashSet<Group>>();
var groupIdUsers = new Dictionary<int, HashSet<User>>();
for(int i = 0; i < result.Length; i += 4)
{
int id;
if(int.TryParse(result[i], out id))
{
string name = result.ElementAtOrDefault(i + 1);
if(name == null)
continue; // end, invalid data
User user = new User{ UserId = id, Name = name };
string groupID = result.ElementAtOrDefault(i + 2);
if(!int.TryParse(groupID, out id))
continue; // end, invalid data
name = result.ElementAtOrDefault(i + 3);
if(name == null)
continue; // end, invalid data
Group group = new Group{ GroupId = id, Name = name };
HashSet<Group> userGroups;
HashSet<User> groupUsers;
if (userIdGroups.TryGetValue(user.UserId, out userGroups))
userGroups.Add(group);
else
userIdGroups.Add(user.UserId, new HashSet<Group>{ group });
if (groupIdUsers.TryGetValue(group.GroupId, out groupUsers))
groupUsers.Add(user);
else
groupIdUsers.Add(group.GroupId, new HashSet<User> { user });
}
}
The result is: 结果是:
You have to override Equals
and GetHashCode
to compare the ID's: 您必须重写
Equals
和GetHashCode
来比较ID:
class User
{
public int UserId { get; set; }
public string Name { get; set; }
public override bool Equals(object obj)
{
User u2 = obj as User;
if (u2 == null) return false;
return UserId == u2.UserId;
}
public override int GetHashCode()
{
return UserId;
}
}
class Group
{
public int GroupId { get; set; }
public string Name { get; set; }
public override bool Equals(object obj)
{
Group g2 = obj as Group;
if (g2 == null) return false;
return GroupId == g2.GroupId;
}
public override int GetHashCode()
{
return GroupId;
}
}
You can do it with the basic structures like loops: 您可以使用像循环这样的基本结构来做到这一点:
void Main()
{
var result = new string[] {"1","John Doe","2","Joes Group","3","Jack Daniel","4","Jacks Group","5","Foo Bar","6","FooBar Group",};
List<Person> personList = new List<Person>();
List<Group> groupList = new List<Group>();
for(int i = 0; i < result.Length; i+=2)
{
i = i + 2;
//check if group does not already exist
groupList.Add(new Group() {Name = result[i+1]});
}
for(int i = 0; i < result.Length; i+=2)
{
//check if person exists.
//if person only add group to person personList.Where(x => x.Name ==result[i+1])....
personList.Add(new Person() { Id = int.Parse(result[i]),
Name = result[i+1],
Groups = new List<Group>()
{
groupList.FirstOrDefault (l => l.Name == result[i+3])
}
});
i = i+2;
}
personList.Dump();
}
public class Person
{
public Person()
{
Groups = new List<Group>();
}
public int Id { get; set; }
public string Name { get; set; }
public List<Group> Groups { get; set; }
}
public class Group
{
public string Name { get; set; }
}
// Define other methods and classes here
Output: 输出:
Please take advise: this code does not contain any validation logic, or duplicate checks. 请注意:此代码不包含任何验证逻辑或重复检查。 You'll have to imlpement this by yourself.
您必须自己植入。 But before you implement something like this, I'd rather change the way you get your data delivered.
但是,在实施此类操作之前,我宁愿更改数据交付方式。 this way you would deal with the root of your peroblems not with the symptoms.
这样,您就可以解决困扰的根源而不是症状。
i think no need to linq 我认为没有必要
//some class //一些类
public class Result
{
public string UserId {get;set;}
public string UserName {get;set;}
public string GroupId {get;set;}
public string GroupName {get;set;}
public string UserGroupUserId {get;set;}
public string UserGroupUserName {get;set;}
public string UserGroupId {get;set;}
public string UserGroupGroupId {get;set;}
}
// your array //您的数组
private void Form1_Load(object sender, EventArgs e)
{
string[] result = new string[8];
result[0] = "1";
result[1] = "John Doe";
result[2] = "121";
result[3] = "SomeGroup";
result[4] = "1";
result[5] = "John Doe";
result[6] = "2135";
result[7] = "SomeOtherGroup";
Result r = CastResult(result);
}
// simple cast array to some type //将简单的转换数组转换为某种类型
public Result CastResult(string[] array)
{
return new Result() { UserId=array[0], UserName=array[1], GroupId=array[2], GroupName=array[3], UserGroupUserId=array[4], UserGroupUserName=array[5] , UserGroupId=array[6], UserGroupGroupId=array[7] };
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.