TGStat
TGStat
Введите текст для поиска
Расширенный поиск каналов
  • flag Russian
    Язык сайта
    flag Russian flag English flag Uzbek
  • Вход на сайт
  • Каталог
    Каталог каналов и чатов Региональные подборки Тематические подборки Платные каналы Поиск каналов
    Добавить канал/чат
  • Рейтинги
    Рейтинг каналов Рейтинг чатов Рейтинг публикаций
    Рейтинги брендов и персон
  • Аналитика
  • Поиск по публикациям
  • Мониторинг Telegram
  • Продвижение
    Реклама через Яндекс Бизнес Реклама в каналах через TGStat Agency Реклама на сайте TGStat.ru
C# Ready | Unity

20 Aug, 14:12

Открыть в Telegram Поделиться Пожаловаться

Почему ToDictionary может упасть на обычных данных?

Когда нужно быстро превратить список в словарь, часто используют ToDictionary. Это удобно, пока ключи уникальные.

Например, есть список пользователей и нужно быстро искать их по email.
var byEmail = users.ToDictionary(u => u.Email);

Код короткий и читаемый. Но он содержит скрытое предположение, что одинаковых email в списке точно нет.

Если из API, CSV или базы прилетят два пользователя с одним ключом, ToDictionary бросит исключение. Он не может сам решить, какой объект оставить.

Если дубли возможны, сначала нужно явно выбрать правило. Например, оставить первый элемент.
var byEmail = users
.GroupBy(u => u.Email)
.ToDictionary(g => g.Key, g => g.First());

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

Если важнее оставить последний элемент, правило тоже должно быть явным.
var byEmail = users
.GroupBy(u => u.Email)
.ToDictionary(g => g.Key, g => g.Last());

А если нужно сохранить все значения одного ключа, лучше использовать ToLookup.
var byEmail = users.ToLookup(u => u.Email);

Lookup похож на словарь, но один ключ может содержать несколько элементов. Это хорошо подходит для тегов, ролей, заказов пользователя и результатов группировки.

Иногда правильнее вообще не чинить дубли в коде, а остановить импорт и показать проблему.
var duplicates = users
.GroupBy(u => u.Email)
.Where(g => g.Count() > 1);

Такой вариант полезен, если email должен быть уникальным по бизнес-правилу. Тогда исключение лучше заменить на понятную ошибку валидации.

Вывод простой. ToDictionary хорош, когда уникальность гарантирована. Если данные приходят извне, сначала реши, что делать с дублями.

В таком случае comparer лучше указать явно.
var byEmail = users
.GroupBy(u => u.Email, StringComparer.OrdinalIgnoreCase)
.ToDictionary(g => g.Key, g => g.First(), StringComparer.OrdinalIgnoreCase);

Без этого можно получить два разных ключа, хотя с точки зрения бизнеса это один и тот же пользователь.

Если данные приходят из внешнего источника, полезно сначала нормализовать ключи.
var email = user.Email.Trim().ToLowerInvariant();

Но нормализация тоже должна быть осознанной. Для одних полей это правильно, для других можно случайно сломать смысл значения.

➡️ C# Ready | #совет

1.2k 0 10 13
Каталог
Каталог каналов и чатов Подборки каналов Поиск каналов Добавить канал/чат
Рейтинги
Рейтинг каналов Telegram Рейтинг чатов Telegram Рейтинг публикаций Рейтинги брендов и персон
API
API статистики API поиска публикаций API Callback
Наши каналы
@TGStat @TGStat_Chat @telepulse @TGStatAPI
Почитать
Академия TGStat Исследование Telegram 2019 Исследование Telegram 2021 Исследование Telegram 2023
Контакты
Справочный центр Поддержка Почта Вакансии
Всякая всячина
Пользовательское соглашение Политика конфиденциальности Публичная оферта
Наши боты
@TGStat_Bot @SearcheeBot @TGAlertsBot @tg_analytics_bot @TGStatChatBot