Гость
Map
Форумы / Java [игнор отключен] [закрыт для гостей] / Смена структуры списка / 12 сообщений из 12, страница 1 из 1
28.10.2020, 10:38
    #40012506
ahmaroot
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Смена структуры списка
Всем доброго дня.
Имеется коллеция объектов List<Order>:
Код: java
1.
[{"type": "BUY", "price": 2132.90, "count": 123},{"type": "SELL", "price": 90.12, "count": 2}, {"type": "BUY", "price": 435, "count": 4}, {"type": "SELL", "price": 32.56, "count": 1}, {"type": "SELL", "price": 77.8, "count": 65}]



Необходимо сделать мапу такого формата:
Код: java
1.
[{"BUY": {123:2132.90, 4:435}},{"SELL": {2: 90.12, 1:32.56, 65:77.8}}]



В идеале конечно же хотелось бы за одну итерацию. Я смотрю в сторону mapName.stream().collect, но пока попытки тщетны. Может кто-то сталкивался с таким?
...
Рейтинг: 0 / 0
28.10.2020, 10:58
    #40012518
PetroNotC Sharp
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Смена структуры списка
ahmaroot
попытки тщетны
покаж
...
Рейтинг: 0 / 0
28.10.2020, 15:53
    #40012693
mad_nazgul
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Смена структуры списка
ahmaroot,

Не истины ради, а флейма для.

Код на Kotlin'е
<:o)

Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
data class Order(
    val type: String,
    val price: Double,
    val count: Int
)

val list = listOf(
    Order("BUY", 2132.90, 123),
    Order("SELL", 90.12, 2),
    Order("BUY", 435.0, 4),
    Order("SELL", 32.56, 1),
    Order("SELL", 77.8, 65)
)

fun main(args: Array<String>) {

    val result =
        list
            .groupingBy { it.type }
            .aggregate {key, accumulator: MutableMap<Int, Double>?, element, first ->
                        if(first) {
                            mutableMapOf(element.count to element.price)
                        } else {
                            accumulator?.apply {
                                put(element.count, element.price)
                            }
                        }
            }

    println(result)
}
...
Рейтинг: 0 / 0
28.10.2020, 17:11
    #40012744
забыл ник
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Смена структуры списка
Ну и на Scala -
Код: java
1.
2.
3.
import cats.implicits._

orders.groupBy(_.type).mapValues(combine)



Только нафига это тут?
...
Рейтинг: 0 / 0
28.10.2020, 18:42
    #40012804
ahmaroot
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Смена структуры списка
Друзья, прошу прощения. Я немного не так сформулировал описание.
Изначально список объетов такой:
Код: java
1.
[{"priceSell": 2132.90, "priceBuy": 3, "count": 123},{"priceSell": 90.12, "priceBuy": 3, "count": 2}, {"priceSell": 39, "priceBuy": 5, "count": 4}]



И на выходе нужно мапу формата вида:
Код: java
1.
[{"BUY": {count:priceBuy}},{"SELL": {count:priceSell}}]




Я пока сделал так:
Код: java
1.
2.
3.
4.
5.
6.
7.
8.
Map<String, Map<String, Double>> response = new HashMap<>() {{
            put("BUY", orders.stream().collect(
                    Collectors.toMap(Order::getCount, Order::getBuyPrice)
            ));
            put("SELL", orders.stream().collect(
                    Collectors.toMap(Order::getCount, Order::getSellPrice)
            ));
        }};



Оно работает. Но минусов много - как минимум 2 раза бежим по одной коллекции. Ну и может как-то это можно оптимизировать и сделать по другому? Спасибо!
...
Рейтинг: 0 / 0
28.10.2020, 19:49
    #40012838
mayton
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Смена структуры списка
ahmaroot

Оно работает. Но минусов много - как минимум 2 раза бежим по одной коллекции. Ну и может как-то это можно оптимизировать и сделать по другому? Спасибо!

Ты какую вообще задачу поставил? Просто решить группировку - это одно. Решить в один проход - это другое.
Решить на Котлин или на Scala или решить с использованием stream это третье. Всё сразу - не будет.

Во всех случаях мы превращаемся в слух и пытаемся понять что-же на самом деле хочет автор
и какого еще птичьего молока ему надо. Вот тебе молоко пингвинов. Вот - страусов. Бери.
...
Рейтинг: 0 / 0
28.10.2020, 20:46
    #40012851
ahmaroot
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Смена структуры списка
ahmaroot
Друзья, прошу прощения. Я немного не так сформулировал описание.
Изначально список объетов такой:
Код: java
1.
[{"priceSell": 2132.90, "priceBuy": 3, "count": 123},{"priceSell": 90.12, "priceBuy": 3, "count": 2}, {"priceSell": 39, "priceBuy": 5, "count": 4}]



И на выходе нужно мапу формата вида:
Код: java
1.
[{"BUY": {count:priceBuy}},{"SELL": {count:priceSell}}]




Я пока сделал так:
Код: java
1.
2.
3.
4.
5.
6.
7.
8.
Map<String, Map<String, Double>> response = new HashMap<>() {{
            put("BUY", orders.stream().collect(
                    Collectors.toMap(Order::getCount, Order::getBuyPrice)
            ));
            put("SELL", orders.stream().collect(
                    Collectors.toMap(Order::getCount, Order::getSellPrice)
            ));
        }};



Оно работает. Но минусов много - как минимум 2 раза бежим по одной коллекции. Ну и может как-то это можно оптимизировать и сделать по другому? Спасибо!


@mayton
Как я понимаю, это н совсем группировка ведь, разве нет? В идеале, повторюсь, хочется обойтись за 1 раз коллекцию. Формат входных и выходных данных, думаю, ясен.
...
Рейтинг: 0 / 0
28.10.2020, 20:58
    #40012853
mayton
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Смена структуры списка
ahmaroot, собеседование что-ли проходишь?

Тогда попробуй напиши эту функцию через обычный цикл на Pure-Java. В 1 проход.
Потом мы попробуем его привести к форме работы со стримами. Но так хоть
будет некая устойчивая точка которая работает. Надо будет написать свою
функцию для reduce или collect.
...
Рейтинг: 0 / 0
28.10.2020, 21:39
    #40012862
забыл ник
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Смена структуры списка
ahmaroot
ahmaroot
Друзья, прошу прощения. Я немного не так сформулировал описание.
Изначально список объетов такой:
Код: java
1.
[{"priceSell": 2132.90, "priceBuy": 3, "count": 123},{"priceSell": 90.12, "priceBuy": 3, "count": 2}, {"priceSell": 39, "priceBuy": 5, "count": 4}]



И на выходе нужно мапу формата вида:
Код: java
1.
[{"BUY": {count:priceBuy}},{"SELL": {count:priceSell}}]




Я пока сделал так:
Код: java
1.
2.
3.
4.
5.
6.
7.
8.
Map<String, Map<String, Double>> response = new HashMap<>() {{
            put("BUY", orders.stream().collect(
                    Collectors.toMap(Order::getCount, Order::getBuyPrice)
            ));
            put("SELL", orders.stream().collect(
                    Collectors.toMap(Order::getCount, Order::getSellPrice)
            ));
        }};



Оно работает. Но минусов много - как минимум 2 раза бежим по одной коллекции. Ну и может как-то это можно оптимизировать и сделать по другому? Спасибо!


@mayton
Как я понимаю, это н совсем группировка ведь, разве нет? В идеале, повторюсь, хочется обойтись за 1 раз коллекцию. Формат входных и выходных данных, думаю, ясен.

В такой постановке это не группировка. Это итерация со стейтом(аккумулирование).
Исторически самым первым решением такой задачи являлось внешнее итерирование в цикле for
Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
int sell = 0
int buy = 0
for(order: orders){
  sell += order.getSell
  buy += order.getBuy
}
map = new HashMap
map.put("SELL", sell)
map.put("BUY", buy)




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

Код: java
1.
2.
3.
4.
5.
6.
int sell = 0;
int buy = 0;
orders.stream().foreach(o => {sell += o.getSell, buy += o.getBuy})
map = new HashMap
map.put("SELL", sell)
map.put("BUY", buy)



Но так как переменные sell и buy у нас мутабельные и могут утечь, усложняем концепцию дальше. Так как твоя операция на математическом языке ассоциативная и коммутативная то для нее всего то и надо что начальное значение и операция, которая должна выполниться над каждым элементом. Вторая часть уже есть, осталось дело за первой. Для этого введем класс-аккумулятор, который будет иммутабельный и на каждом проходе будет создаваться его модифицированная копия. Также стоит отметить что объект класса создается прямо в методе reduce и никуда утечь не может.

Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
public class Accum(sell int, buy int){
  public int getSell() = {return sell}
  public int getBuy() = {return buy}
}

либо с использованием Lombok - 
@Data
public class Accum(sell int, buy int)

либо в новой java 
record Accum(sell int, buy int)

Accum result = orders.stream.reduce(new Accum(0,0), (order, accum) => new Accum(accum.getBuy + order.getBuy, accum.getSell + order.getSell))
map = new HashMap
map.put("SELL", result.getSell)
map.put("BUY", result.getBuy)



В теории можно обойтись и без промежуточного класса и объекта accum, но код будет выглядеть громоздким(на Java)

Код: java
1.
2.
3.
4.
5.
6.
7.
8.
public Map initMap() = {
map = new HashMap
map.put("SELL", 0)
map.put("BUY", 0)
return map
}

orders.stream.reduce(initMap(), (map, order) => { map.put("BUY", map.get("BUY") + order.getBuy), map.put("SELL", map.get("SELL") + order.getSell) }



Еще больше можно абстрагировать логику вводя математическое понятие Monoid, это такая алгебраическая структура, которая имеет начальное значение некого типа и бинарную ассоциативную операцию, результатом которой будет элемент того же типа что и начальное значение. Это позволяет еще более абстрагировать и переиспользовать код, но это уже далеко за рамками ООП и java-новичка.
...
Рейтинг: 0 / 0
28.10.2020, 23:10
    #40012890
mayton
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Смена структуры списка
Не дай бог еще собеседующий будет знать что такое моноиды, и абелевы группы и скажет - Ану-ка давай ка поговорим про это...
...
Рейтинг: 0 / 0
29.10.2020, 05:43
    #40012934
mad_nazgul
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Смена структуры списка
забыл ник
[
Еще больше можно абстрагировать логику вводя математическое понятие Monoid, это такая алгебраическая структура, которая имеет начальное значение некого типа и бинарную ассоциативную операцию, результатом которой будет элемент того же типа что и начальное значение. Это позволяет еще более абстрагировать и переиспользовать код, но это уже далеко за рамками ООП и java-новичка.


У вас по дороге цена потерялась :-)

Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
data class Order(
    val type: String,
    val price: Double,
    val count: Int
)

val list = listOf(
    Order("BUY", 2132.90, 123),
    Order("SELL", 90.12, 2),
    Order("BUY", 435.0, 4),
    Order("SELL", 32.56, 1),
    Order("SELL", 77.8, 65)
)

fun main(args: Array<String>) {

    val result =
        list
            .groupingBy { it.type }
            .aggregate {key, accumulator: Pair<Int, Double>?, element, first ->
                        if(first) {
                            element.count to element.price
                        } else {
                            (accumulator?.first?:0 + element.count) to (accumulator?.second?:0.0 + element.price)
                        }
            }

    println(result)
}
...
Рейтинг: 0 / 0
29.10.2020, 05:45
    #40012935
mad_nazgul
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Смена структуры списка
mad_nazgul,

Прошу прощения. Одно сравнение лишнее.

Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
data class Order(
    val type: String,
    val price: Double,
    val count: Int
)

val list = listOf(
    Order("BUY", 2132.90, 123),
    Order("SELL", 90.12, 2),
    Order("BUY", 435.0, 4),
    Order("SELL", 32.56, 1),
    Order("SELL", 77.8, 65)
)

fun main(args: Array<String>) {

    val result =
        list
            .groupingBy { it.type }
            .aggregate {key, accumulator: Pair<Int, Double>?, element, first ->
                        (accumulator?.first?:0 + element.count) to (accumulator?.second?:0.0 + element.price)
            }

    println(result)
}
...
Рейтинг: 0 / 0
Форумы / Java [игнор отключен] [закрыт для гостей] / Смена структуры списка / 12 сообщений из 12, страница 1 из 1
Целевая тема:
Создать новую тему:
Автор:
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]