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

How to properly use LINQ Query on List<KeyValuePair<string, string> to create Dictionary<KeyValuePair<string, string>, int>?

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

为了提供一些上下文,此方法在 .NET/DNN 网络表单中调用,以验证我们的一位客户上传的文件;表格可以有重复的发票号,但不能有重复的发票和零件号;因此,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 应突出显示为红色;前几行中突出显示的其他单元格都可以(空字段的其他验证器)。

编辑:包括一个可重现的例子。这是我第一次 post 在这里所以请批评我的礼节!谢谢!

这很好用:

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