Ruby - месяц_группы за текущий год, включая месяцы без данных - PullRequest
0 голосов
/ 08 мая 2019

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

Пользователь может вводить даты пройденных миль, поэтому в модели Mile у меня есть атрибуты start_date и end_date.

В настоящее время у меня есть метод close , однако он должен возвращать 0 для текущего месяца, поскольку пользователь не набрал ни одного мили, пройденного за май. Я также должен ограничить это текущим годом, которым он в настоящее время не является.

Вот как выглядит мой текущий метод:

def miles_by_month
    miles = self.miles.from_this_year.group_by { |t| t.start_date.strftime('%b') }
    total_miles = miles.map do |m|
        { 'indicator': m[0], 'total': m[1].sum(&:length) }
    end
    total_miles
end

И область 'from_this_year' для модели Mile, если это полезно:

scope :from_this_year, lambda { where("start_date > ? AND start_date < ?", Time.now.beginning_of_year, Time.now.end_of_year) }

А вот пример того, что он возвращает:

[
    [0] {
        :indicator => "Jan",
            :total => 15
    },
    [1] {
        :indicator => "Feb",
            :total => 10
    },
    [2] {
        :indicator => "Mar",
            :total => 10
    },
    [3] {
        :indicator => "Apr",
            :total => 100
    },
    [4] {
        :indicator => "May",    # I need [4] to show up with 
        :total => 0             # a total of 0. [4] currently
    }                           # does not show up at all.
]

«Индикатор» относится к названию месяца, а «итог» относится к сумме миль, пройденных пользователем за этот конкретный месяц.

Есть предложения?

ОБНОВЛЕНИЕ 1

Я несколько изменил свой метод miles_by_month, основанный на ответе здесь:

def miles_by_month
    months = Date::ABBR_MONTHNAMES[1..12]
    miles = self.miles.from_this_year.group_by { |t| t.start_date.strftime('%b') }

    total_miles = miles.map do |m|
        { 'indicator': m[0], 'total': m[1].sum(&:length) }
    end

    months.each do |month|
      unless total_miles.any? { |r| r[:indicator] == month }
        total_miles.push(indicator: month, total: 0)
      end
    end

    total_miles
  end

Единственное, что мне нужно сделать, это выяснить, как ограничить переменную month от начала года до текущего месяца.

Ответы [ 2 ]

2 голосов
/ 08 мая 2019

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

MONTHS = Date::ABBR_MONTHNAMES[1..12]

# put this somewhere
MONTHS.each do |month|
  unless results.any? { |r| r[:indicator] == month }
    results.push(indicator: month, total: 0)
  end
end

# you can sort them chronologically if needed
results.sort_by! { |r| MONTHS.index(r[:indicator]) }

Обратите внимание, что это не самый эффективный код - в нем есть некоторые O (N ^ 2) вещи, которые можно оптимизировать до O (N) - но мы надеемся, что это даст вам отправную точку

0 голосов
/ 09 мая 2019

Основываясь на ответе Макса Плинера, я смог придумать следующий метод, чтобы правильно вернуть то, что мне нужно:

def miles_by_month
    cur_month = Time.now.month
    months = Date::ABBR_MONTHNAMES[1..cur_month]
    miles = self.miles.from_this_year.group_by { |t| t.start_date.strftime('%b') }

    total_miles = miles.map do |m|
        { 'indicator': m[0], 'total': m[1].sum(&:length) }
    end

    months.each do |month|
      unless total_miles.any? { |r| r[:indicator] == month }
        total_miles.push(indicator: month, total: 0)
      end
    end

    total_miles
  end

Это возвращает структуру данных, подобную следующей:

[
    [0] {
        :indicator => "Jan",
            :total => 15
    },
    [1] {
        :indicator => "Feb",
            :total => 10
    },
    [2] {
        :indicator => "Mar",
            :total => 10
    },
    [3] {
        :indicator => "Apr",
            :total => 100
    },
    [4] {
        :indicator => "May",
            :total => 0
    }
]

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

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