У меня есть rowsDictionary
что его ключи указывают на список классов EmployeeSummary
. В этих классах EmployeeSummary
у нас также есть строковое свойство Delivery_System
Я прохожу через это таким образом, но теперь застрял в той части, в которой я хочу иметь deliverySystemFinder dictioanry
что ее ключи combinedKey
как deliverySystemFinder dictioanry
ниже, а значение для каждого ключа - это список различных значений delivery_system
//rowsDictionary is a Dictionary<string, List<EmployeeSummary>>
Dictionary<string, List<string>> deliverySystemFinder = new Dictionary<string, List<string>>();
foreach (string key in rowsDictionary.Keys)
{
List<EmployeeSummary> empList = rowsDictionary[key];
foreach (EmployeeSummary emp in empList)
{
string combinedKey = emp.LastName.Trim().ToUpper() + emp.FirstName.Trim().ToUpper();
string delivery_system = emp.Delivery_System;
// so now I should go and
//A) does deliverySystemFinder have this combinedKey? if not add it.
//B) Does combinedKey in the list of its values already have the value for delivery_system? if it does not then add it
}
}
Это будет работать, для начала:
foreach (string key in rowsDictionary.Keys)
{
List<EmployeeSummary> empList = rowsDictionary[key];
foreach (EmployeeSummary emp in empList)
{
string combinedKey = emp.LastName.Trim().ToUpper() +
emp.FirstName.Trim().ToUpper();
string delivery_system = emp.Delivery_System;
List<string> systems = null;
// check if the dictionary contains the list
if (!deliverySystemFinder.TryGetValue(combinedKey, out systems))
{
// if not, create it and add it
systems = new List<string>();
deliverySystemFinder[combinedKey] = systems;
}
// check if the list contains the value and add it
if (!systems.Contains(delivery_system))
systems.Add(delivery_system);
}
}
Теперь несколько замечаний:
Не имеет смысла итерации через Keys
, а затем выполнять поиск на каждой итерации. Вы можете напрямую перебирать KeyValuePair
с помощью цикла foreach
.
Использование конкатенированных строк в качестве уникальных ключей часто терпит неудачу. В этом случае, что произойдет, если у вас есть пользователи { LastName="Some", FirstName="Body" }
и { LastName="So", FirstName="Mebody" }
в вашем списке?
Проверка того, что List
содержит значение, является операцией O(n)
. Вы бы значительно повысили производительность, если вместо этого использовали HashSet<string>
.
Наконец, самый простой способ добиться того, что вы пытаетесь сделать, - это прорвать эти циклы и просто использовать:
// returns a Dictionary<EmployeeSummary, List<string>>
// which maps each distinct EmployeeSummary into a list of
// distinct delivery systems
var groupByEmployee = rowsDictionary
.SelectMany(kvp => kvp.Value)
.GroupBy(s => s, new EmployeeSummaryEqualityComparer())
.ToDictionary(
s => s.Key,
s => s.Select(x => x.Delivery_System).Distinct().ToList());
С EmployeeSummaryEqualityComparer
определено что-то вроде:
class EmployeeSummaryEqualityComparer : IEqualityComparer<EmployeeSummary>
{
public bool Equals(EmployeeSummary x, EmployeeSummary y)
{
if (object.ReferenceEquals(x, null))
return object.ReferenceEquals(y, null);
return
x.FirstName == y.FirstName &&
x.LastName == y.LastName &&
... (depending on what constitutes 'equal' for you)
}
public int GetHashCode(EmployeeSummary x)
{
unchecked
{
var h = 31; // null checks might not be necessary?
h = h * 7 + (x.FirstName != null ? x.FirstName.GetHashCode() : 0);
h = h * 7 + (x.LastName != null ? x.LastName.GetHashCode() : 0);
... other properties similarly ...
return h;
}
}
}
Если вы действительно думаете, что использование string
ключа будет работать во всех ваших случаях, вы можете сделать это без специального сопоставления равенства:
// returns a Dictionary<string, List<string>>
var groupByEmployee = rowsDictionary
.SelectMany(kvp => kvp.Value)
.GroupBy(s => s.LastName.ToUpper() + s.FirstName.ToUpper())
.ToDictionary(
s => s.Key,
s => s.Select(x => x.Delivery_System).Distinct().ToList());