Помогите, пожалуйста, решить задачку. Дано:
public enum GroupType { None = 0x0000
, Name = 0x0001
, Ext = 0x0002
, Type = 0x0004
};
Dictionary<int, GroupType> d;
d = new Dictionary<int, GroupType> { {1, GroupType.Name}
, {2, GroupType.Name | GroupType.Type}
, {3, GroupType.Type}
};
В результате должно получиться
Dictionary<GroupType, List<int>> dRes;
dRes = { {GroupType.Name, {1, 2}}
, {GroupType.Type, {2, 3}}
};
То есть, для каждого значения побитовой маски должен быть выделен набор ключей, которые присутствуют в исходном наборе.
GroupType.None битовая маска «0» введена для того, чтобы выбирать именно элементы без всех ключей. Сравнение идет по равенству. Чтобы не сравнивать == 0, а делать == GroupType.None
Enum.HasFlag
для нулевой маски возвращает всегда true, т.ч. нужно будет написать вспомогательный метод, чтобы реализовать подобное сравнение:
private static bool HasFlag(GroupType value, GroupType flag)
{
if(flag==GroupType.None) return ((int) value)==0;
return value.HasFlag(flag);
}
После этого можно выбрать все значения перечисления в список:
var types = Enum.GetValues(typeof(GroupType))
.Cast<GroupType>()
.ToList();
И использовать список для выборки значений словаря и группировки:
var dRes = d
//для каждой записи в словаре выбираем все типы в паре с ключом
.SelectMany(entry => types.Where(t => HasFlag(entry.Value, t)).Select(t => new {t, entry.Key}))
//группируем по типу
.GroupBy(pair => pair.t, pair => pair.Key)
//переводим в словарь
.ToDictionary(group => group.Key, group => group.ToList());
Альтернативно, можно сделать выборку из types
и для каждого типа выбрать подходящие ключи из словаря.
Демо на ideone: https://ideone.com/OMCtY9
Вот таким образом можно добится требуемого результата
var enumValues = Enum.GetValues(typeof(GroupType));
Dictionary<GroupType, List<int>> result = new Dictionary<GroupType, List<int>>();
foreach (var p in d)
{
uint flags = (uint)p.Value;
foreach (var enumValue in enumValues)
{
if ((flags & (int)enumValue) != 0)
{
GroupType group = (GroupType)enumValue;
if (result.ContainsKey(group))
{
List<int> list = result[group];
list.Add(p.Key);
}
else
{
List<int> list = new List<int>() { p.Key };
result.Add(group, list);
}
}
}
}
Суть: читаем значение из словаря. Далее бежим по всем элементам перечисления GroupType
и проверяем, имеется ли флаг перечисления в текущем значении(для этого делаем операцию &
, если флаг не установлен, то битовая операция И вернет 0, иначе != 0
). В случае, если перечисление имеется в существующем значении, то добавляем элемент в результирующий словарь.
Кофе для программистов: как напиток влияет на продуктивность кодеров?
Рекламные вывески: как привлечь внимание и увеличить продажи
Стратегії та тренди в SMM - Технології, що формують майбутнє сьогодні
Выделенный сервер, что это, для чего нужен и какие характеристики важны?
Современные решения для бизнеса: как облачные и виртуальные технологии меняют рынок
Недавно сделал для себя открытие - при сборкеNET-приложения я могу выбрать разрядность целевой платформы