2014-09-26 31 views
1

我有一種情況,我以這種方式從數據庫獲取數據,所有內容都存儲在一維數組中。
例如:使用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] = "SomeGroup" // group name 
result[4] = "1" // user id 
result[5] = "John Doe" // user name 
result[6] = "2135" // group id 
result[7] = "SomeOtherGroup" // group name 

我知道這不是保持數據的一個很好的解決方案,但這些數據是來從其他一些我不允許改變的代碼給我,所以我必須處理它。

我的問題是:

  1. 這是可能的,以分析該陣列和地方數據在我自己的對象(用戶類組集合在它)使用LINQ。
  2. 如果不是由LINQ處理,其他什麼最好的方法是什麼?
+0

因此,一個用戶可以屬於多個組(這將在這種情況下重複用戶)。所有用戶都屬於哪個用戶? – 2014-09-26 11:18:20

+0

它是多對多的關係。一個用戶可以屬於多個組,一個用戶組可以包含多個用戶。 – Dawid 2014-09-26 11:20:56

+0

那麼你如何區分用戶和組? – 2014-09-26 11:24:43

回答

2

純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()}); 
  • 在使用地板和臨時變量4點的元件的子集的第一GroupBy I組的結果。
  • 然後下一個Select將得到的數組放在匿名類型中,以便在接下來的步驟中更好地實用。
  • 下一個GroupBy用於按員工分組條目。密鑰將是員工,這些值將是相應的組。
  • 最後的激光Select是用來把GroupBy結果在一個更好的形狀。我選擇將結果放入其他匿名類型中,但您可以在此實例化自定義對象,並使用大括號構造函數將值放入正確的字段中。
+0

你需要添加'int i = 0;'。它不會編譯沒有它 – Marco 2014-09-26 11:36:19

+0

哎呀我的錯誤! – Seb 2014-09-26 11:37:14

+0

您的解決方案非常棒!謝謝。你會如此善良耐心地逐步解釋它是如何工作的?我真的不明白會發生什麼。 – Dawid 2014-09-26 12:21:24

0

你可以用基本的結構做這樣的循環:

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 

輸出:

enter image description here

請大家指教:這個代碼不包含任何驗證邏輯,或複製檢查。你必須自己動手。 但是在你實現這樣的事情之前,我寧願改變你傳遞數據的方式。這樣你就可以處理你的問題的根源而不是症狀。

-1

我覺得沒有必要LINQ

//一些類

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] }; 
    } 
1

如果你的邏輯依賴於索引LINQ很少是正確的工具。與普通循環相比,它的可讀性,可維護性,有效性和可靠性都較差。

我會用像下面這樣的東西來創建兩個代表多對多關係的字典。注意for -loop其在每次迭代遞增4,因爲這似乎是用戶組 - 「包」:

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 }); 
    } 
} 

結果是:

  • 用戶詞典包含一個用戶兩組
  • 組,字典包含兩組其映射到同一個用戶

您必須覆蓋EqualsGetHashCode來比較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; 
    } 
}