2017-04-14 59 views
0

我在下面的C#类,并希望根据该人居住的地址创建一个不同的家庭列表。如果他们有相同的地址,他们就是家人。所以它应该有一个家庭名单,每个家庭都有一个家庭成员名单。C#嵌套类列表<>

public class Person 
    { 
     public string firstName; 
     public string lastName; 
     public Address address; 

     public Person(string f, string l, string addr, string city, string state) 
     { 
      firstName = f; 
      lastName = l;  
      address= new Address(addr, city, state); 
     } 
    } 

    public class Family 
    { 
     public string familyAddress;//maybe I don't need this 
     public List<Person> personList; 

     public Family() 
     { 
      personList = new List<Person>(); 
     } 

     public void AddPerson(Person p) 
     { 
      personList.Add(p); 
     } 

     public string FamilyAddress //maybe I dont need this 
     { 
      get 
      { 
       return familyAddress; 
      } 
      set 
      { 
       familyAddress= value; 
      } 
     } 
    } 

    public partial class Form1 : Form 
    { 
     public List<Family> familyList; 

     public Form1() 
     { 
      InitializeComponent(); 
     } 

     private void Form1_Load(object sender, EventArgs e) 
     { 
      familyList= new List<Family>(); 
      ReadCustomerFile("..\\Customers.txt"); 
     } 

     private void ReadCustomerFile(file) 
     { 
      var lines = File.ReadAllLines(file);     
      var reg = new Regex("(?:^|,)(\"(?:[^\"]+|\"\")*\"|[^,]*)"); 

      for (int i = 0; i < lines.Length; i++) 
      { 
       var data = reg.Matches(lines[i]).Cast<Match>().Select(m => m.Value).ToArray(); 

       //data[0] contains first name 
       //data[1] contains last name 
       //data[2] contains street 
       //data[3] contains city 
       //data[4] contains state 

      //In here as I read the customer text file, i would 
      //like to add the person that has the same address into 
      //the same family. 
      //for example: 
      //familyList address: "800 NE Oregon St. Portland, OR" has 
      //      "Steve Jones" 
      //      "Sarah Jones" 
      //      "Alisa Jones" 

      //familyList address: "2525 Lake Park. Salt Lake City, UT" has 
      //      "Joey William" 
      //      "Becky William" 
      //      "Sam William" 
      } 
     } 
    } 

更新#1-基于Tempx评论:谢谢!

public partial class Form1 : Form 
    { 
     public List<Family> familyList; 
     public List<Person> personList; 

     public Form1() 
     { 
      InitializeComponent(); 
     } 

     private void Form1_Load(object sender, EventArgs e) 
     { 
      familyList= new List<Family>(); 
      personList = new List<Person>();     

      ReadCustomerFile("..\\Customers.txt"); 
     } 

     private void ReadCustomerFile(file) 
     { 
      var lines = File.ReadAllLines(file);     
      var reg = new Regex("(?:^|,)(\"(?:[^\"]+|\"\")*\"|[^,]*)"); 

      for (int i = 0; i < lines.Length; i++) 
      { 
       var data = reg.Matches(lines[i]).Cast<Match>().Select(m => m.Value).ToArray(); 

       //data[0] contains first name 
       //data[1] contains last name 
       //data[2] contains street 
       //data[3] contains city 
       //data[4] contains state 
       Person person = new Person(data[0].Trim(','), 
              data[1].Trim(','), 
              data[2].Trim(','), 
              data[3].Trim(','), 
              data[4].Trim(',')); 
       personList.Add(person); 
      } 

      //In here as I read the customer text file, i would 
      //like to add the person that has the same address into 
      //the same family. 
      //for example: 
      //familyList address: "800 NE Oregon St. Portland, OR" has 
      //      "Steve Jones" 
      //      "Sarah Jones" 
      //      "Alisa Jones" 

      //familyList address: "2525 Lake Park. Salt Lake City, UT" has 
      //      "Joey William" 
      //      "Becky William" 
      //      "Sam William" 

      var familyAddress = new Dictionary<Address, Family>(); 
      Family family; 
      foreach (Person p in personList) 
      { 
       // Returns true if the familyAddess contains the address of the person 
       if (familyAddress.TryGetValue(p.address, out family)) 
        //if such family exists add the person the family 
        family.AddPerson(p); 
       else // no family is found with the person's address 
       { 
        //create a new family 
        family = new Family(); 
        //add person to the family 
        family.AddPerson(p); 
        //add the family to the familyAddress dictionary 
        familyAddress.Add(p.address, family); 
       } 
      } 

     } 
    } 

本声明

if (familyAddress.TryGetValue(p.address, out family)) 

总是返回家不存在,所以它去else语句

UPDATE#2现在可以加入人的家庭。但是现在有时候人们的地址在逗号和逗号的时间里,尽管街道名称,城市和州是相同的。所以它导致Dictionary键TryGetValue()返回不需要的结果。 TryGetValue()可能会忽略逗号和句点吗?谢谢

public partial class Form1 : Form 
    { 
     public List<Family> familyList; 
     public List<Person> personList; 

     public Form1() 
     { 
      InitializeComponent(); 
     } 

     private void Form1_Load(object sender, EventArgs e) 
     { 
      familyList= new List<Family>(); 
      personList = new List<Person>();     

      ReadCustomerFile("..\\Customers.txt"); 
     } 

     private void ReadCustomerFile(file) 
     { 
      var lines = File.ReadAllLines(file);     
      var reg = new Regex("(?:^|,)(\"(?:[^\"]+|\"\")*\"|[^,]*)"); 

      for (int i = 0; i < lines.Length; i++) 
      { 
       var data = reg.Matches(lines[i]).Cast<Match>().Select(m => m.Value).ToArray(); 
       Person person = new Person(data[0].Trim(','), 
              data[1].Trim(','), 
              data[2].Trim(','), 
              data[3].Trim(','), 
              data[4].Trim(',')); 
       personList.Add(person); 
      } 

      var familyAddress = new Dictionary<string, Family>(); 
      Family family; 
      foreach (Person p in personList) 
      { 
       // Returns true if the familyAddess contains the address of the person 
       if (familyAddress.TryGetValue(p.address.GetAddress(), out family)) 
        //if such family exists add the person the family 
        family.AddPerson(p); 
       else // no family is found with the person's address 
       { 
        //create a new family 
        family = new Family(); 
        //add person to the family 
        family.AddPerson(p); 
        //add the family to the familyAddress dictionary 
        familyAddress.Add(p.address, family); 
       } 
      } 

     } 
    } 

UPDATE#3-我决定将地址字符串格式化为正确的格式,然后我添加为字典中的键。转换后列出类似下面以下Tempx建议:

var valueList = familyAddress.Values.ToList(); 

我如何可以遍历目录?因为我尝试以下:

 foreach (var h in valueList) 
     { 
      foreach(var p in h) 
      { 
       //I cannot access the Person data? 
      } 
     } 

感谢

+1

什么是你的问题? –

+0

“它应该有一个家庭列表,每个家庭都应该有一个家庭成员列表。”它看起来像你的代码已经有这个。 – Vassalware

+3

您似乎未能提出问题。我有一个给你,虽然 - 为什么是“Address”在一个类中表示为一个字符串,而在另一个类中表示为实际类型? –

回答

1

我相信你想的人添加到正确的家庭,相信你可以使用字典做的工作。

public List<Person> personList; 

//a specific address points to a specific family 
var familyAddress = new Dictionary<Address, Family>(); 

在开始我假设personList不是空的,但familyAddress是。

然后,在你的代码,用于人员名单语句可以写成

foreach (person p in personList) 
{ 
    // Returns true if the familyAddess contains the address of the person 
    if (familyAddress .TryGetValue(p.Address, out family)) 
     //if such family exists add the person the family 
     family.AddPerson(p); 
    else // no family is found with the person's address 
    { 
     //create a new family 
     family = new Family(); 
     //add person to the family 
     family.AddPerson(p); 
     //add the family to the familyAddress dictionary 
     familyAddress.add(p.Address, family); 
    } 
} 

可以检索的家庭名单,作为

familyAddress.Values.ToList(); 

PS:由于其他评论者说我也相信Family类familyAddress应该是Address类型。

+0

感谢您的回复。我想过使用字典,但我宣布结构错了,字典<字符串,列表>所以我无法将该人添加到具有相同地址,键的列表中。所以我明天会试试你的建议。再次感谢。 – Phil

+0

看起来这是“if(familyAddress.TryGetValue(p.Address,out family))”没有正确返回,因为我在调试模式下检查familyAddress和p.Address中的两个地址,它们是相同的地址,但条件转到“其他”声明。 – Phil

+0

地址可能相同,但它们是相同的对象吗?例如,Address a1和Address a2可能包含相同的地址,但由于它们是不同的对象,我相信TryGetValue可能无法正常工作。我很抱歉。你可以尝试的是,而不是Address对象作为字典的关键字,你可以使用它的字符串值。 (在这种情况下,您可以在Address类中添加一个静态方法,例如toString(),它将Address转换为其字符串等效项。) – tempx

1

如果您想要改用LINQ,您可以通过LINQ将List<Person>转换为List<Family>。下面是一个扩展方法,将做到这一点:

public static class FamilyExtensions 
{ 
    public static List<Family> GroupToFamilies(this List<Person> personList) 
    { 
     var retval = from p in personList 
        group p by new p.address into f 
        select new Family() { personList = f.ToList() }; //If familyAddress was of type Address, you could add: familyAddress = f.Key 
     return retval.ToList(); 
    } 
} 

然后,你可以打电话给你的方法,你的代码的地方......

List<Person> people = new List<Person>(); 

people.Add(new Person("Papa", "Bear", "123 Forest Rd", "Somewhere", "AK")); 
people.Add(new Person("Mama", "Bear", "123 Forest Rd", "Somewhere", "AK")); 
people.Add(new Person("Some", "Bear", "567 Woodland Ln", "Somewhere", "AK")); 
people.Add(new Person("Other", "Bear", "890 Canopy Cr", "Somewhere", "AK")); 

var families = people.GroupToFamilies(); 

需要注意的是,如果你想按p.address,你会需要在您的Address课程上覆盖GetHashCode()Equals(object obj)。如果你不希望覆盖这两种方法,则可以选择按组合键:

from p in personList 
group p by new { p.address.addr, p.address.city, p.address.state } into f 
select new Family() { personList = f.ToList() }; 

如果你想按Address,您Address类重写GetHashCode()Equals(object obj)是这样的...

public class Address 
{ 
    /*** Rest of your class ***/ 

    public override bool Equals(object obj) 
    { 
     var address = obj as Address; 

     return address != null 
      && address.addr == this.addr 
      && address.city == this.city 
      && address.state == this.state; 
    } 

    public override int GetHashCode() 
    { 
     int hash = 41; 
     hash = (hash * 79) + addr.GetHashCode(); 
     hash = (hash * 79) + city.GetHashCode(); 
     hash = (hash * 79) + state.GetHashCode(); 
     return hash; 
    } 
} 

Here's more information on the group clause in C#

+0

感谢您的建议。 LINQ将在我未来的自我研究主题中,但现在我想保持代码简单。谢谢。 – Phil