嵌套的foreach循环仅返回distinct

时间:2015-02-11 18:54:59

标签: c# loops datatable

我有一个数据库,每个电子邮件地址应该属于一个独特的客户,但我有很多重复。我使用sql查询列出了每个事件的客户ID,电子邮件地址对,其中有多个客户ID映射到单个电子邮件地址。结果看起来像这样(地址改变以保护无辜者)

Customer ID   Email
101233        bob@myaddress.com
108993        bob@myaddress.com
113224        bob@myaddress.com
89223         mary@otherdomain.com
188223        mary@otherdomain.com

在c#中,我将其填充到名为dt的DataTable中,其中包含722行。我使用它来制作第二个名为distinctTbl的DataTable,其中344行只包含不同的电子邮件地址:

DataTable distinctTbl = dt.AsDataView().ToTable(true, "Email");

我正在尝试使用嵌套循环为每个电子邮件地址创建一个整数列表(客户ID):

foreach (DataRow dr in distinctTbl.Rows)
{
    // for each email address:
    List<int> idNums = new List<int>();

    foreach (DataRow myRow in dt.Rows) 
    {
        // for every customerID / email pair in the original table
        if (myRow["Email"] == dr["Email"])
        {
            idNums.Add((int)myRow["CustomerID"]);
        }
    }

    // Do something with the List<int> before exiting outside loop
}

当我运行此代码时,每个整数列表只包含一个值。值是正确的,但每个电子邮件地址应至少有两个。我做了足够的调试,以确定它始终正确识别第一个,但跳过任何后续匹配。我确定我错过了一些明显的东西,但有人看到发生了什么吗?

2 个答案:

答案 0 :(得分:2)

一个快速简便的解决方案是使用Dictionary<string,List<int>>而不是列表:

    Dictionary<string, List<int>> idNums = new Dictionary<string, List<int>>();
    foreach (DataRow myRow in dt.Rows)
    {
        string email = myRow["Email"].ToString()
        if (idNums.ContainsKey(email))
        {
            idNums[email].Add((int)myRow["CustomerID"]);
        }
        else
        {
            idNums.Add(email, new List<int> { (int)myRow["CustomerID"] });
        }
    }

现在,idNums将包含与每封电子邮件关联的ID列表。

答案 1 :(得分:2)

抛弃foreach循环。

您可以使用Linq更轻松地获取您正在寻找的信息。

Dictionary<string, List<int>> emailIDs =
    dt.Rows.OfType<DataRow>()
           .GroupBy(row => (string)row["Email"])
           .ToDictionary(grp => grp.Key,
                         grp => grp.Select(row => (int)row["CustomerID"]).ToList());