Kotlin - создать объект на основе суммы - PullRequest
0 голосов
/ 19 мая 2019

У меня есть вопрос.У меня есть следующий класс

data class Item(val month: Int, val year: Int, val value: Int)

И у меня есть список

val items = listOf(
    Item(month = 1, year = 2019, value = 5000),
    Item(month = 1, year = 2019, value = 200),
    Item(month = 1, year = 2019, value = 300),
    Item(month = 1, year = 2019, value = 1000),
    Item(month = 2, year = 2019, value = 5000),
    Item(month = 2, year = 2019, value = 6000),
    Item(month = 3, year = 2019, value = 500),
    Item(month = 3, year = 2019, value = 1500),
    Item(month = 5, year = 2019, value = 900),
    Item(month = 1, year = 2020, value = 700)
)

Я хочу суммировать значения объектов Item, имеющих одинаковые месяц и год, исоздать еще один объект Item с полем month, year и sum в качестве значения

val result = listOf(
    Item(month = 1, year = 2019, value = 6500),
    Item(month = 2, year = 2019, value = 11000),
    Item(month = 3, year = 2019, value = 2000),
    Item(month = 5, year = 2019, value = 900),
    Item(month = 1, year = 2020, value = 700)
)

Как этого добиться?Спасибо

1 Ответ

5 голосов
/ 19 мая 2019

Сначала вы группируете по месяцу + году (при условии, что это должно быть уникальным).Затем вы сопоставляете это с новым элементом, в котором значением являются значения каждой группы.

items.groupBy { "${it.month}/${it.year}" } даст вам что-то вроде этого:

{
  '01/2019': [
    Item(month = 1, year = 2019, value = 5000),
    Item(month = 1, year = 2019, value = 200),
    Item(month = 1, year = 2019, value = 300),
    Item(month = 1, year = 2019, value = 1000)
  ],
  '02/2019': ...
}

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

items.groupBy { "${it.month}/${it.year}" }
     .map {
            Item(it.value.first().month, 
                 it.value.first().year,
                 it.value.sumBy(Item::value))
        }

Результат в моем коде выглядит точно так же, как ваш пример вывода.

Обновление:

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

data class Date(var month: Int, var year: Int)

Теперь вы группируете по объекту Date, который вы создаете на лету, а также распаковываете значение:

    items.groupBy({ Date(it.month, it.year) }, { it.value })

Это создает карту, подобнуюthis:

{
    { month: 1, year: 2019 }: [ 5000, 200, 300, 1000 ],
    { month: 2, year: 2019 }: [ ... ]
}

После этого вы можете отобразить это так же, как и раньше, но с более чистым доступом к члену:

items.groupBy({ Date(it.month, it.year) }, { it.value })
     .map {
         Item(it.key.month,
              it.key.year,
              it.value.sum())
     }

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

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