Как правильно использовать LINQ Query для List <KeyValuePair <string, string> для создания словаря <KeyValuePair <string, string>, int>? - PullRequest
0 голосов
/ 18 июня 2019

Я пытаюсь создать запрос LINQ для List<KeyValuePair<string, string>>, который сообщает мне, сколько (если есть) дубликатов KeyValue в списке. Для этого я попытался создать Dictionary<KeyValuePair<string, string>, int>, где ключом словаря является KeyValuePair из списка, а значением словаря является число раз, которое пара встречается в исходном списке. Мой код компилируется, но в настоящее время он говорит мне, что каждая из KeyValuePairs в списке дублируется.

Чтобы обеспечить некоторый контекст, этот метод вызывается в веб-форме .NET / DNN для проверки файла, загруженного одним из наших клиентов; форма МОЖЕТ иметь дубликаты номеров счетов, но может не иметь дубликатов счетов и номеров деталей; следовательно, List<KeyValuePair<string, string>> представляет собой сочетание номеров счетов и номеров деталей. Значение int в словаре должно указывать количество раз, когда каждая пара номеров счетов-фактур появляется в главном списке. Данные извлекаются из элемента управления GridView, который содержит данные из файла загрузки.

За последние пару часов я проработал кучу статей LINQ, чтобы попытаться повторить код для создания словаря с таким списком, но мне это не удалось. Эта статья предоставила много полезной информации:

C # LINQ найти дубликаты в списке

Также обратите внимание, что этот код реализован в 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 голосов
/ 18 июня 2019

Это прекрасно работает:

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