C# 使用LINQ将存储在一维数组中的记录分组
我有一种情况,我从数据库中获取数据的方式是,所有数据都存储在一维数组中。C# 使用LINQ将存储在一维数组中的记录分组,c#,sql,arrays,linq,C#,Sql,Arrays,Linq,我有一种情况,我从数据库中获取数据的方式是,所有数据都存储在一维数组中。 例如: User table: UserId, Name Group table: GroupId, Name UserGroup table: UserId, GroupId 通过连接这些表,我获得了以下形式的数组: result[0] = "1" // user id result[1] = "John Doe" // user name result[2] = "121" // group id result[3]
例如:
User table: UserId, Name
Group table: GroupId, Name
UserGroup table: UserId, GroupId
通过连接这些表,我获得了以下形式的数组:
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
我知道这不是一个保存数据的好方法,但是这些数据是从我不允许更改的其他代码中获得的,所以我必须处理它。我的问题是:
您可以使用循环之类的基本结构来实现:
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
void Main()
{
var result=新字符串[]{“1”、“John Doe”、“2”、“Joes组”、“3”、“Jack Daniel”、“4”、“Jacks组”、“5”、“Foo Bar”、“6”、“FooBar组”、};
List personList=新列表();
List groupList=新列表();
对于(int i=0;ix.Name==result[i+1])。。。。
添加(newPerson(){Id=int.Parse(结果[i]),
名称=结果[i+1],
组=新列表()
{
groupList.FirstOrDefault(l=>l.Name==result[i+3])
}
});
i=i+2;
}
personList.Dump();
}
公共阶层人士
{
公众人士()
{
组=新列表();
}
公共int Id{get;set;}
公共字符串名称{get;set;}
公共列表组{get;set;}
}
公共课组
{
公共字符串名称{get;set;}
}
//在此处定义其他方法和类
输出:
请注意:此代码不包含任何验证逻辑或重复检查。你必须自己完成这个。
但在您实现类似的功能之前,我宁愿改变您获取数据的方式。这样你就可以解决问题的根源,而不是症状。我认为没有必要 //一些班级
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;}
}
//您的阵列 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);
}
//将数组简单转换为某种类型 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] };
}
纯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()});
- 在第一个
I组中,使用一个floor和一个临时变量生成4个元素子集GroupBy
- 接下来的
将生成的数组放在匿名类型中,以便在接下来的步骤中更好地使用选择
- 下一个
用于按员工对条目进行分组。键将是员工,值将是相应的组GroupBy
- 最后,lase
用于将Select
结果设置为更好的形状。我选择将结果放在另一个匿名类型中,但您可以在这里实例化自定义对象,并使用花括号构造函数将值放在正确的字段中GroupBy
,它在每次迭代中递增4,因为这似乎是用户组-“package”:
因此,一个用户可以属于多个组(在本例中,它将重复该用户)。所有用户所属的组是否也对每个用户重复?这是多对多关系。一个用户可以属于多个组,一个组可以包含多个用户。那么如何区分用户和组?可能仅通过索引和重复模式我只知道查询结果显示多少列。我知道包含此结果数组的对象的RowCount和ColumnCount属性。例如,要获取我使用的第i条记录的组名:result[i*ColumnCount+3]。您需要添加inti=0代码>。没有它就无法编译你的解决方案太棒了!非常感谢。你能耐心地一步一步地解释它是如何工作的吗?我真的不明白会发生什么。是的,我会修改我的答案。有十几个原因导致此查询可能失败;-)@我认识我的朋友。我看到两个主要问题:结果。长度%4!=0和result.Any(x=>x==null)。这两种情况都可以通过一些预先检查来避免:P
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 });
}
}
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;
}
}