как проверить что в словаре что-то есть?

static void Main(string[] args)
{
    Dictionary<string, Dictionary<string, string>> dict = new Dictionary<string, Dictionary<string, string>>();
    if (dict)
    {
        Console.WriteLine("1");
    }
}

Есть словарь со вложенным словарем. Как написать условие, которое бы сразу проверяло наличие данных в словаре и срабатывало бы, если в словарях что-то есть, и не срабатывало, если в них ничего нет?


Ответы (2 шт):

Автор решения: Швеев Алексей

Проверить наличие ключа в словаре:

public bool ContainsKey(TKey key);

Пример:

if (dict.ContainsKey(5))
{
    Console.WriteLine("dict[5] существует");
}

Получить значение по ключу в словаре, если ключ в нём содержится:

public bool TryGetValue(TKey key, [MaybeNullWhen(false)] out TValue value);

Данный метод нужен что бы не делать поиск ключа дважды когда тебе надо его получить, но ты не уверен в его существовании.

Пример использования:

if (dict.TryGetValue(6, out var value))
{
    Console.WriteLine($"dict[6] == {value}");
}
else
{
    Console.WriteLine("dict[6] не существует");
}

Проверить наличие значения в словаре:

public bool ContainsValue(TValue value);

Отлично работает если TValue является типом значений (например int, string, struct и другие примитивные типы)

Таким образом для

Dict<string, int> dict { {"key", 5} };
dict.ContainsValue(5);

Вернёт true

Однако с ссылочными типами (такие как наши объекты и т. п.) есть нюанс

ContainsValue(TValue value) для ссылочных типов использует value.Equals метод для поиска нужного объекта.

А по умолчанию (для object и всего, что его наследует) он сравнивает ссылки на этот объект. Таким образом для класса

class Test
{
    public int v = 5;
}

var dict = new Dictionary<int, Test>()
{
    {5, new Test() {v = 5 } },
};

код

if (dict.ContainsValue(dict[5]))
    Console.WriteLine("true");
else
    Console.WriteLine("false")

выведет true, ведь dict[5] и dict[5] это один и тот же объект

Однако этот код

if (dict.ContainsValue(new Test() { v = 5 }))
    Console.WriteLine("true");
else
    Console.WriteLine("false");

выведет false, ведь new создаёт новый объект.

P. S.: С типами значений, даже при прописывании new всё работать будет, т. к. так устроена память

Если же мы хотим, что бы код выше заработал нам необходимо переопределить метод Equals:

class Test
{
    public int v = 5;
    public override bool Equals(object? obj)
    {
        if (obj is Test test) // Если тип второго объекта такой же
            return test.v == v; // то возвращаем true, если v совпадают
        return base.Equals(obj); // иначе стандартная проверка
    }
}

Теперь код

if (dict.ContainsValue(new Test() { v = 5 }))
    Console.WriteLine("Test {v=5} существует");

сработает

Получить ключ/значение элемента с помощью linq и своего компаратора:

Мы так же можем использовать linq методы для поиска. Таким образом мы можем найти значение используя не конкретное значение, а компаратор. Допустим у нас есть словарь:

var dict = new Dictionary<string, Dictionary<string, string>>()
{
    {
        "key1",
        new()
        {
            { "kkey1", "ok!" }
        }
    },
    {
        "key2",
        new()
        {
            { "kkey2", "ok2!" }
        }
    }
}; 

Что эквивалентно этому в json:

{
    key1: {
        kkey1: 'ok!'
    },
    key2: {
        kkey2: 'ok2!'
    }
}

И мы хотим получить такой ключ внешнего словаря, у которого во внутреннем словаре имеется значение ok2! (в нашем случае это key2)

Это можно реализовать так:

// Ищем первое вхождение, у которого у значения имеется значение ok2!
var key = dict.First(e => e.Value.ContainsValue("ok2!")).Key;

Сюда вы можете поставить любую функцию, которая будет проверять значение (а может даже и ключ).

Вообще linq имба, вот ещё пример, где мы очищаем все вхождения, где ключ == значение:

Тут так же можно увидеть, как преобразовать IEnumerable<KeyValuePair<...>> в Dictionary<...>

var dict = new Dictionary<string, string>()
{
    { "a", "a" },
    { "b", "c" }
};
var filteredDict = dict.Where(e => e.Key != e.Value).ToDictionary(v => v.Key, v => v.Value);
// filteredDict == {b: "c"}
→ Ссылка
Автор решения: MRGRD56

Если нужно узнать, содержит ли словарь элементы, можно использовать его свойство Count

if (dict.Count > 0) {
  // словарь не пуст - содержит элемент(ы)
} else {
  // словарь пуст - не содержит элементов
}
→ Ссылка