Список дат заказа для сравнения - PullRequest
0 голосов
/ 04 февраля 2019

Ранее я задавал этот вопрос здесь: Список дат, заказанных определенным образом

Я думал, что предложенное решение было в порядке до года, отмеченного на моемсписок дат и столкнулся с проблемой.

Мой список дат (в этом строковом формате - так данные поступают ко мне из исходного API)

201711
201712
201801
201811
201812
201901

Я хочу представить свои данные в гистограмме, чтобы показать Сравнение годового показателя за 3 месяца в месячном порядке .Это будет означать, что я упорядочу список следующим образом:

201711
201811
201712
201812
201801
201901

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

Я пробовалРешение в нижней части вопроса, но он размещает порядок следующим образом (а это не то, что я хочу):

201801
201901
201711
201811
201712
201812

Для ясности, в следующем месяце нужно будет двигаться вперед, чтобы оказаться в этом списке дат:

первый месяц, который я хочу, всегда будет за 2 месяца до текущего

201712
201812
201801
201901
201802
201902

var rowsInOrder = dateList.OrderBy(n => DateTime.ParseExact(n, "yyyyMM", CultureInfo.CurrentCulture).Month).ThenBy(n=> DateTime.ParseExact(n, "yyyyMM", CultureInfo.CurrentCulture).Year);

Ответы [ 4 ]

0 голосов
/ 04 февраля 2019

Таким образом, вы застряли с последовательностью объектов, где каждый объект имеет свойство Date типа string в формате yyyyMM.и вы хотите извлечь из него некоторые данные.

Ваш формат даты не зависит от языка.Не имеет значения, является ли ваш компьютер британским или китайским.Свойство Date всегда будет иметь формат yyyyMM.

Это позволяет довольно легко преобразовать его в формат DateTime, что упрощает доступ к году и месяцу.

const string dateTimeFormat = "yyyyMM";
CultureInfo provider = CultureInfo.InvariantCulture;
var dateList = ...      // your original list of items with the string Date property

var itemsWithYearMonth = dateList.Select(item => new
{
    DateTime = DateTime.ParseExact(item, dateTimeFormat, provider)
    ... // select other items you need for your bar chart
});

Сейчасс учетом StartYear / Month, NrOfYears и NrOfMonths, которые вы хотите сгруппировать dateTimeItems в группы одного и того же месяца.

Например, начиная с 2018-11, я хочу группы с четырьмя месяцами в течение трех лет подряд (да, да, я знаю, что в вашем первоначальном запросе это было всего 3 месяца, 2 года, но зачем ограничиваться этим, давайте сделаем ваш код многократно используемым):

group 1: 2018-11, 2019-11, 2020-11, 2021-11
group 2: 2018-12, 2019-12, 2020-12, 2021-12
group 3: 2019-01, 2020-01, 2021-01, 2022-01

Бонусные баллы: мы 'Пройдем границу года!

Итак, введите:

var itemsWithYearMonth = ... // see above
int startYear = ...
int startMonth = ...
int nrOfMonths = ...    
int nrOfYears = ...

Мы создадим группы предметов с одинаковыми месяцами.Мы не хотим все месяцы года, мы хотим только несколько месяцев.Если мы хотим, чтобы 3 месяца начинались с 11 месяца, нам нужно сохранить группы с месяцами 11, 12, 1.

var desiredMonths = Enumerable.Range(startMonth, nrOfMonths)   // example: 11, 12, 13
    .Select(monthNr => 1 + ((monthNr-1) % 12));                // 11, 12, 1

Исходя из вашего ввода, мы не хотим все месяцы, нам нужны толькогод / месяц больше, чем начальный месяц.

DateTime startMonth = new DateTime(startYear, startMonth, 1);

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

var result = itemsWithYearMonth
    // keep only the items newer than startMonth
    .Where(item => item.DateTime >= startMonth)

    // group by same month:
    .GroupBy(item => item.DateTime.Month,
    (month, itemsWithThisMonth) => new
    {
        Month = month,        // in my example: 11, 12, 1, ...

        // in every group: take the first nrOfYears items:
        Items = itemsWithThisMonth
                // order by ascending year
                .OrderBy(itemWithThisMonth => itemWithThisMonth.Year)
                // no need to order by Month, all Months are equal in this group
                .Take(nrOfYears)
                .ToList(),
     })
     // keep only the desired months:
     .Select(group => desiredMonth.Contains(group.Month));

Итак, теперь у вас есть группы:

group of month 11, with data of years 2018, 2019, 2020, 2021
group of month 12, with data of years 2018, 2019, 2020, 2021
group of month 01, with data of years 2019, 2020, 2021, 2022
0 голосов
/ 04 февраля 2019

Вы можете использовать этот подход поиска, который сначала определяет группы месяцев:

var monthLookup = dateList
    .Select(s => new{String = s, Date = DateTime.ParseExact(s, "yyyyMM", CultureInfo.CurrentCulture)})
    .OrderBy(x => x.Date)  // not necessary in your sample data but i assume it's desired
    .ToLookup(x=> x.Date.Month);
var rowsInOrder = monthLookup.SelectMany(x => x).Select(x => x.String);
0 голосов
/ 04 февраля 2019

Мне кажется, что этого достаточно:

var rowsInOrder = dates.OrderBy(x => x).GroupBy(x => x.Substring(4)).SelectMany(x => x);

Нет необходимости просто разбираться с датами разбора.Это простая сортировка строк и группировка таким образом.

0 голосов
/ 04 февраля 2019

Мне удалось достичь вашей цели, используя GroupBy для группировки месяцев,

var rowsInOrder = new List<string>();
foreach (var grouping in dates.GroupBy(s =>
        DateTime.ParseExact(s, "yyyyMM", CultureInfo.CurrentCulture).Month))
{
    rowsInOrder.AddRange(grouping.OrderBy(s => s));
};

Вы также можете заказать месяцы с такой же логикой:

var rowsInOrder = new List<string>();
foreach (var grouping in dates
    .OrderBy(s => DateTime.ParseExact(s, "yyyyMM", CultureInfo.CurrentCulture).Month).GroupBy(s =>
        DateTime.ParseExact(s, "yyyyMM", CultureInfo.CurrentCulture).Month))
{
    rowsInOrder.AddRange(grouping.OrderBy(s => s));
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...