如何在List <KeyValuePair <string,string>上正确使用LINQ查询来创建Dictionary <KeyValuePair <string,string>,int>?

时间:2019-06-18 16:01:56

标签: c# .net linq duplicates dotnetnuke

我正在尝试在List<KeyValuePair<string, string>>上创建LINQ查询,该查询告诉我列表中有多少个KeyValue重复项(如果有)。为此,我尝试创建一个Dictionary<KeyValuePair<string, string>, int>,其中字典的关键字是列表中的KeyValuePair,字典的值是该配对在原始列表中出现的次数。我的代码可以编译,但是目前它告诉我列表中的每个KeyValuePairs都是重复的。

为了提供一些上下文,在.NET / DNN Web表单中调用此方法以验证由我们的一个客户端上传的文件。该表格可能有重复的发票编号,但可能没有重复的发票和零件编号;因此,List<KeyValuePair<string, string>>代表发票编号和零件编号的配对。字典的int值应报告每个发票和零件编号对出现在主列表中的次数。数据是从包含文件上传数据的GridView控件中提取的。

在过去的几个小时中,我在这里研究了很多LINQ文章,尝试复制用于创建具有此类列表的字典的代码,但是我一直没有成功。本文提供了许多有用的信息:

C# LINQ find duplicates in List

此外,请注意,此代码是在DNN中实现的,这使得调试非常困难。我无法单步执行代码来确定问题所在,因此请耐心等待。

private void CheckBranchNumbersFile(GridView Upload)
{
    List<KeyValuePair<string, string>> invoiceAndPart = new List<KeyValuePair<string, string>>();

    for (int i = 0; i < Upload.Rows.Count; ++i)
    {
        KeyValuePair<string, string> pair = new KeyValuePair<string, string>(Upload.Rows[i].Cells[2].ToString(), Upload.Rows[i].Cells[5].ToString());
        invoiceAndPart.Add(pair);
    }

    List<KeyValuePair<string, string>> invoiceAndPartUnsorted = new List<KeyValuePair<string, string>>(invoiceAndPart);

    var query = invoiceAndPart.GroupBy(x => x).Where(g => g.Count() > 1).ToDictionary(x => x.Key, y => y.Count());
    foreach (KeyValuePair<KeyValuePair<string, string>, int> invPartCount in query)
    {
        int count = invPartCount.Value;
        if (count > 1)
        {
            IsNotValid = true;
            for (int i = 0; i < invoiceAndPartUnsorted.Count; ++i)
            {
                if (invoiceAndPartUnsorted[i].Key.Equals(invPartCount.Key.Key) && invoiceAndPartUnsorted[i].Value.Equals(invPartCount.Key.Value))
                {
                    // This block highlights the cells on the review screen for the client to see erroneous data
                    Upload.Rows[i].Cells[2].BackColor = Color.Red;
                    Upload.Rows[i].Cells[5].BackColor = Color.Red;
                    Upload.Rows[i].Cells[2].ToolTip = "Cannot have duplicate invoice AND part numbers";
                    Upload.Rows[i].Cells[5].ToolTip = "Cannot have duplicate invoice AND part numbers";
                }
            }
        }
    }
}

请参见以下可重现的示例:

// Populate list with sample invoice/part numbers, including some duplicates

List<KeyValuePair<string, string>> data = new List<string, string>();
KeyValuePair<string, string> sample1 = new KeyValuePair<string, string>("ABC", "100");
KeyValuePair<string, string> sample2 = new KeyValuePair<string, string>("FFF", "250");
KeyValuePair<string, string> sample3 = new KeyValuePair<string, string>("XYZ", "100");
KeyValuePair<string, string> sample4 = new KeyValuePair<string, string>("ABC", "100");
KeyValuePair<string, string> sample5 = new KeyValuePair<string, string>("ABC", "100");

data.Add(sample1);
data.Add(sample2);
data.Add(sample3);
data.Add(sample4);
data.Add(sample5);

// Create copy of data before data is grouped by LINQ query

List<KeyValuePair<string, string>> data2 = new List<string, string>(data);

// Perform LINQ Query to create Dictionary<KeyValuePair<string, string>, int> that reports number of occurences of each KeyValuePair<string, string> in @variable ata

var query = data.GroupBy(x => x).Where(g => g.Count() > 1).ToDictionary(x => x.Key, y => y.Count());

// Using foreach loop, identify the indices in @variable data2 that contain duplicated entries
foreach (KeyValuePair<KeyValuePair<string, string>, int> pair in query)
{
   int count = pair.Value;

   // This pair represents a duplicate because its value > 1
   if (count > 1)
   {
      // Find the entry in data2 that matches this pair
      for (int i = 0; i < data2.Count; ++i)
      {
         if (data2[i].Equals(pair.Key))
         {
            Console.WriteLine("Match in list data2 found at index: " + i);
         }
      }
   }
}

// The console should write:
// Match in list data2 found at index: 0
// Match in list data2 found at index: 3
// Match in list data3 found at index: 4

// Thank you! :)

我希望检查屏幕仅将具有重复的发票和零件号的行的单元格标记为错误,但是它将为文件中每行数据标记这些单元格。例如,如果输入的Excel文件中总共有10行,其中3行包含重复的发票和零件号,则这些单元格必须被涂成红色并用工具提示标记,而不是全部10行。每行的单元格2和5分别包含发票编号和零件编号。以下是其当前操作的屏幕截图:https://gyazo.com/a2c8203627fe81f763c48008d0ba9e33

在此示例中,仅最后3行应将单元格2和5突出显示为红色;上一行中突出显示的其他单元格都可以(其他验证器用于空白字段)。

编辑:包括一个可复制的示例。这是我在这里的第一篇文章,所以请批评我的礼节!谢谢!

1 个答案:

答案 0 :(得分:0)

这很好用:

         var data = new List<KeyValuePair<string, string>>
         {
            new KeyValuePair<string, string>("ABC", "100"),
            new KeyValuePair<string, string>("FFF", "250"),
            new KeyValuePair<string, string>("XYZ", "100"),
            new KeyValuePair<string, string>("ABC", "100"),
            new KeyValuePair<string, string>("ABC", "100")
         };

         // Create copy of data before data is grouped by LINQ query

         var data2 = data.ToList();

         // Perform LINQ Query to create Dictionary<KeyValuePair<string, string>, int> that reports number of occurences of each KeyValuePair<string, string> in @variable ata

         var query = data.GroupBy(x => x).Where(g => g.Count() > 1).ToDictionary(x => x.Key, y => y.Count());

         // Using foreach loop, identify the indices in @variable data2 that contain duplicated entries
         foreach (var pair in query)
         {
            int count = pair.Value;

            // This pair represents a duplicate because its value > 1
            if (count > 1)
            {
               // Find the entry in data2 that matches this pair
               for (int i = 0; i < data2.Count; ++i)
               {
                  if (data2[i].Equals(pair.Key))
                  {
                     Console.WriteLine("Match in list data2 found at index: " + i);
                  }
               }
            }
         }