У меня есть список дат рождения. Я хочу преобразовать его по возрастной группе. то есть: группа 1: возраст 0 - 15 лет, группа 2: возраст 15-20 лет и т. д. - PullRequest
0 голосов
/ 04 апреля 2020
 var allBirthdate = await _Repository.GetAll().Where(x => x.DateOfBirth.HasValue).
                Select(x => x.DateOfBirth.Value).ToListAsync();

Ответы [ 3 ]

0 голосов
/ 04 апреля 2020

Добавьте свойство (только для чтения) в свой класс или напишите расширение для расчета возрастной группы:

public int AgeGroup
{
    get
    {
        if (!DateOfBirth.HasValue)
        {
            return 0;
        }
        int year = DateTime.Now.Year;
        int age = DateTime.Now.Year - DateOfBirth.Value.Year;
        return
            age <= 15 ? 1 :
            age <= 20 ? 2 :
            age <= 35 ? 3 :
            age <= 60 ? 4 : 5;
    }
}

Затем получите словарь с идентификатором возрастной группы (1,2, 3) в качестве ключа и список экземпляров вашего класса, которые попадают в эту возрастную группу в качестве значения, например:

Dictionary<int, List<Person>> byAgeGroup = people
    .GroupBy(x => x.AgeGroup)
    .ToDictionary(x => x.Key, x => x.ToList());
0 голосов
/ 04 апреля 2020

Вот простое консольное приложение, которое использует аналогичный подход, описанный @Oguz Ozgul:

using System;
using System.Collections.Generic;
using System.Linq;

namespace ConsoleApp3
{
    internal class Person
    {
        public string Name { get; set; }
        public DateTime DateOfBirth { get; set; }

        public int Age
            => (int) Math.Floor((DateTimeOffset.UtcNow - DateOfBirth).TotalDays / 365);

        public int AgeGroup
        {
            get
            {
                if (Age < 15) // [0,14]
                    return 1;
                if (Age < 20) // [15,19]
                    return 2;
                if (Age < 30) // [20,29]
                    return 3;
                if (Age < 40) // [30,39]
                    return 4;
                if (Age < 60) // [40, 59]
                    return 5;
                return 6; // 60+
            }
        }
    }

    internal class Program
    {
        private static readonly Dictionary<int, string> _ageGroupRanges
            = new Dictionary<int, string>
            {
                {1, "0 to 14"},
                {2, "15 to 19"},
                {3, "20 to 29"},
                {4, "30 to 39"},
                {5, "40 to 59"},
                {6, "60+"}
            };

        private static void Main(string[] args)
        {
            var people = new List<Person>
            {
                new Person {Name = "Joe", DateOfBirth = new DateTime(1980, 01, 01)},
                new Person {Name = "Dan", DateOfBirth = new DateTime(1982, 01, 01)},
                new Person {Name = "Laura", DateOfBirth = new DateTime(2010, 01, 01)},
                new Person {Name = "Beth", DateOfBirth = new DateTime(2020, 01, 01)}
            };
            var peopleGroupedByAge = people
                .GroupBy(p => p.AgeGroup)
                .OrderBy(g => g.Key);

            foreach (var group in peopleGroupedByAge)
            {
                var ageGroup = group.Key;
                var ageGroupRange = _ageGroupRanges[ageGroup];
                var namesOfPeopleInGroup = string.Join(", ", group.Select(p => p.Name));
                Console.WriteLine($"Age group {ageGroup} ({ageGroupRange}): {namesOfPeopleInGroup}");
            }

            Console.ReadKey(true);
        }
    }
}

Наиболее важные биты - это вычисленные свойства Age и AgeGroup, добавленные к Person объект. Пройдите по коду в отладчике и осмотрите там значения - вы увидите, что они инкапсулируют логику c, вычисляющую, к какой возрастной группе человек относится.

Наконец, нам нужно сгруппировать наши Person объекты в группы в зависимости от их возрастной группы. Мы можем добиться этого методом GroupBy:

var peopleGroupedByAge = people
    .GroupBy(p => p.AgeGroup)
    .OrderBy(g => g.Key);
0 голосов
/ 04 апреля 2020

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

private static (List<Person> OlderPersons, List<Person> YoungerPersons) GroupByAgeV1(List<Person> people, DateTime refDate)
{
  var groupedDates = people.Where(x => x.DateOfBirth.HasValue).GroupBy(p => p.DateOfBirth >= refDate).ToList();

  var olderPersons = groupedDates.Where(g => g.Key == false)
                      .Select(g => g.ToList())
                      .ToList()
                        .FirstOrDefault();
  var youngerPersons = groupedDates.Where(g => g.Key == false)
                    .Select(g => g.ToList())
                    .ToList()
                      .FirstOrDefault();

  return (OlderPersons: olderPersons, YoungerPersons: youngerPersons);

}

Этот подход кажется лучше и проще для чтения в вашем случае

private static (List<Person> OlderPersons, List<Person> YoungerPersons) GroupByAgeV2(List<Person> people, DateTime refDate)
{
  var peopleHasBirtDate = people.Where(x => x.DateOfBirth.HasValue).ToList();

  var olderPersons = peopleHasBirtDate.Where(p => p.DateOfBirth >= refDate).ToList();
  var youngerPersons = peopleHasBirtDate.Where(p => p.DateOfBirth < refDate).ToList();

  return (OlderPersons: olderPersons, YoungerPersons: youngerPersons);

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