Хранить и группировать на основе всех записей словаря, где соответствует X

#c# #linq

#c# #linq

Вопрос:

У меня есть Dictionary , CustomerInfo_Dict , который хранит CustomerID (Key) | Age (Value)

  1. Получить distinct Age (Value)

  2. Добавьте совпадающую CustomerID (Key) базу для каждого отдельного Age (Value) в Array/List/other type

      foreach (var CustomerInfo_Dict_DistinctAge in CustomerInfo_Dict.Values.Distinct())
     {
         foreach (var CustomerInfo in CustomerInfo_Dict)
         {
             //if (CustomerInfo <Value>:Age) == (CustomerInfo_Dict_DistinctAge <Value>:Age)
             {
                 //add matched `CustomerID (Key)` to a separate List
             }
         }
     }
      

Комментарии:

1. Итак, вы хотите поменять местами свой словарь? Создать словарь, который сопоставляет возраст-> список идентификаторов с этим возрастом?

Ответ №1:

Требуется только один цикл (не LINQ)

 var ageToIds = new Dictionary<int, List<int>>();

foreach(var kvp in idToAge){
  if(!ageToIds.ContainsKey(kvp.Value))
    ageToIds[kvp.Value] = new List<int>();

  ageToIds[kvp.Value].Add(kvp.Key);
}
  

И с помощью LINQ мы можем заставить LINQ создать группу по значению (возрасту), которое станет ключом, и вся KeyValuePair станет списком значений (из которого мы затем можем выбрать только ключ.. но обратите внимание, что это ключ KeyValuePair, а не ключ группировки):

 var ageToIds = idToAge
  .GroupBy(kvp => kvp.Value)
  .ToDictionary(
    g => g.Key,
    g => g.Select(kvp => kvp.Key).ToList()
  );
  

Возможно, вы даже сможете пропустить часть словаря, потому что игрофикация Linq — это почти то же самое:

 var ageToIdsGrouping = idToAge
  .GroupBy(kvp => kvp.Value, kvp => kvp.Key);
  

Это дает вам GroupedEnumerable, который похож на словарь, если вы его перечисляете; это коллекция группировок, каждая группировка имеет ключ (который является возрастом) и сама является перечислимым из целых чисел (которые являются идентификаторами)

 foreach(var g in ageToIdsGrouping){
      int age = g.Key;
      var ids = g;     //it's an enumerable list of the IDs
      string idsString = string.Join(',', ids);
        
      Console.WriteLine($"{age}: {idsString}");
}
  

Если у вас было это раньше:

 idToAge[123] = 30;
idToAge[234] = 30;
idToAge[345] = 30;
idToAge[456] = 31;
  

У вас должно быть это:

 ageToIds[30] = { 123, 234, 345 };
ageToIds[31] = { 456 };
  

Чтобы получить все списки:

 foreach(var kvp in ageToIds){

  int age = kvp.Key;

  List<int> ids = kvp.Value;

}
  

Комментарии:

1. Спасибо! Я пытаюсь использовать вашу версию, отличную от LINQ. Я вижу, что вы добавили value в a new List , если в ключе нет совпадения. После запуска я получаю все созданные списки, перебирая каждый ключ foreach(var kvp in idToAge) , чтобы получить все ageToIds[kvp.Value] созданные списки? * извинения, я хотел сказать, что я не могу придумать метод получения всех созданных списков после выполнения вышеуказанного.