Подсчет групп людей в возрастных диапазонах

У меня есть небольшой способ получить количество участников в определенном возрастном диапазоне. Предполагается, что диапазон включает оба конца, т. е. если я назову CountSelection(memberList, 16, 19) (где memberList — это List<Member>), я ожидаю получить общее количество участников в возрасте 16, 17, 18 и 19 лет:

private int CountSelection(List<Member> members, int minAge, int maxAge)
{
    DateTime from = DateTime.Now.AddYears(minAge * -1);
    DateTime to = DateTime.Now.AddYears(maxAge * -1);
    return members.Count(m =>
        m.DateBorn.Date <= from.Date && 
        m.DateBorn.Date >= to.Date);
}

Однако мой метод ненадежен - иногда он пропускает членов, я предполагаю, что когда даты рождения попадают между диапазонами. В основном методе я вызываю CountSelection() несколько раз, каждый с разными диапазонами, теоретически охватывающими все возрасты.

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

Я думаю, что ваши даты from и to поменялись местами. Судя по тому, как написан ваш код, дата to соответствует дате доfrom, что кажется неправильным.

user47589 09.04.2019 17:48

Вам не нужно умножать на -1, вы можете просто инвертировать выражение напрямую. Например, DateTime.Now.AddYears(-minAge) :)

Yeldar Kurmangaliyev 09.04.2019 18:04

Возраст не совпадает с годом рождения человека...

Alexei Levenkov 09.04.2019 18:05

Вопрос в том, если кто-то родился в феврале 2017 года, им два или три года? Если maxAge = 2, они не включаются. Когда у вас есть диапазон, минимум должен быть >=, а максимум должен быть только <, иначе у вас будет один дополнительный день.

jdweng 09.04.2019 18:13

Использовать DateTime.Date.AddYears? DateTime.Now.AddYears включает компонент времени.

Steve Todd 09.04.2019 18:38
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
5
228
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Я понял, почему мой метод не работает. Я просто вычитал целые годы из дат от и до, и в результате диапазоны выглядели следующим образом (формат даты дд.мм.гггг):

0-5 years - 11.04.2014-11.04.2019
6-12 years - 11.04.2007-11.04.2013
13-19 years - 11.04.2000-11.04.2006
20-26 years - 11.04.1993-11.04.1999
... and so on.

Обратите внимание на разрыв почти в год между каждым диапазоном.

Решение:

Вместо того, чтобы устанавливать дату начала следующим образом:

DateTime from = DateTime.Now.Date.AddYears(-maxAge);

Я, конечно, должен вычесть еще 1 год и добавить 1 день:

DateTime from = DateTime.Now.Date.AddYears(-maxAge + 1).AddDays(1);

Теперь диапазоны выглядят так:

0-5 years - 12.04.2013-11.04.2019
6-12 years - 12.04.2006-11.04.2013
13-19 years - 12.04.1999-11.04.2006
20-26 years - 12.04.1992-11.04.1999
... and so on.

Окончательный рабочий метод выглядит так:

private int CountSelection(List<Member> members, int minAge, int maxAge)
{
    DateTime from = compareDate.AddYears(-maxAge+1).AddDays(1);
    DateTime to = compareDate.AddYears(-minAge);
    return members.Count(m => 
        m.DateBorn >= from && 
        m.DateBorn <= to);
}

С диапазонами с исключающими верхними границами работать проще:

private int CountSelection(List<Member> members, int minAge, int maxAgeExclusive)
{
    DateTime from = compareDate.AddYears(-maxAgeExclusive);
    DateTime to = compareDate.AddYears(-minAge);
    return members.Count(m => m.DateBorn > from && m.DateBorn <= to);
}

Теперь ваши диапазоны будут математически более последовательными.

0-6 years
6-13 years
13-20 years
20-27 years
etc

Затем вы можете вычесть единицу из верхнего предела на уровне представления.

Другие вопросы по теме