Гость
Map
Форумы / Java [игнор отключен] [закрыт для гостей] / Разбить list на list из sublist / 6 сообщений из 6, страница 1 из 1
25.09.2020, 11:02
    #40002451
hsadik
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Разбить list на list из sublist
Есть условный список с объектами.
Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
List<String> list = new ArrayList<>();
list.add("A");
list.add("B");
list.add("C");
list.add("D");
list.add("E");
list.add("F");
list.add("G");
list.add("H");
list.add("K");
list.add("L");


Я хочу разбить список на отдельные списки, в котором будет по 3 элемента.
Т.е. результат должен быть такой: [[A, B, C], [D, E, F], [G, H, K], [L]]

В Google Guava и Apache Commons есть метод, который выполняет эту работу. В Guava это например так:
Код: java
1.
Lists.partition(list, 3)



У меня вопрос, можно ли обойтись без сторонних библиотек и хитроумных манипуляций вроде этой (далее пример со stackoverflow):
Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
public static <T> Stream<List<T>> batches(List<T> source, int length) {
    if (length <= 0)
        throw new IllegalArgumentException("length = " + length);
    int size = source.size();
    if (size <= 0)
        return Stream.empty();
    int fullChunks = (size - 1) / length;
    return IntStream.range(0, fullChunks + 1).mapToObj(
        n -> source.subList(n * length, n == fullChunks ? size : (n + 1) * length));
}



Например, используя стримы?
Находил похожее решение для чисел:
Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
final List<List<Integer>> groups = range(0, numbers.size())
            .boxed()
            .collect(groupingBy(index -> index / 4))
            .values()
            .stream()
            .map(indices -> indices
                    .stream()
                    .map(numbers::get)
                    .collect(toList()))
            .collect(toList());


Но проблема в том, что для объектов я не могу сделать такую группировку. Что можно придумать?
...
Рейтинг: 0 / 0
25.09.2020, 12:03
    #40002475
chpasha
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Разбить list на list из sublist
keep it simple
в чем задача-то? чтоб было понятно, максимально компактно, максимально быстро, чтоб без внешних зависимостей или чтоб просто работало?

hsadik
Но проблема в том, что для объектов я не могу сделать такую группировку

в смысле, какую группировку для каких объектов? то решение, которое ты нашел (на стримах) - оно не для чисел, а универсальное. Это стандартный прием с range, когда в стриме нужен индекс элемента, а не сам элемент

Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
List<String> list = asList("A", "B", "C", "D", "E", "F", "G", "H", "I", "J");
List<List<String>> collect = IntStream.range(0, list.size())
                                              .boxed()
                                              .collect(Collectors.groupingBy(idx -> idx / 3))
                                              .values()
                                              .stream()
                                              .map(indices -> indices.stream()
                                                                     .map(list::get)
                                                                     .collect(Collectors.toList()))
                                              .collect(Collectors.toList());

System.out.println(collect);
// [[A, B, C], [D, E, F], [G, H, I], [J]]



как по мне код слегка не очевиден, т.е. через месяц придется морщить мозг, пытаясь понять wtf тут происходит. Но если очень хочется и назвать метод понятно, то можно.
...
Рейтинг: 0 / 0
25.09.2020, 19:05
    #40002655
mayton
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Разбить list на list из sublist
21-й век пройдет под флагом функциональщины. Это очевидно. Но стоит-ли нам ВСЕГДА искать решение а-ля
stream-processing? Может быть мы сначала решим задачу императивно? Посмотрим. А потом уже от него подойдем
к поточно-иммутабельной e.t.c.

Просто есть задачи где ФП реально летает (описание грамматик) и без него невозможно и есть другой
мир. Мир процессоров и регистров и памяти с кешами.
...
Рейтинг: 0 / 0
25.09.2020, 19:22
    #40002659
mayton
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Разбить list на list из sublist
Я-бы усугубил задачу. Не нужен вам List. Он предполагает интерфейс индексатора. А его в природе
может тоже не быть. Вы данные можете тоже получать из внешнего мира не как массив.
А тоже как поток чего-то неогранченного. Больше чем Integer.MAX_INT элементов.

Попробуйте решить вот в таком ключе

Код: java
1.
2.
3.
public static <T> Stream<List<T>> batches(Stream<T> source, int length) {
...
}



или так. Это тоже самое. (Есть обертка для перехода).

Код: java
1.
2.
3.
public static <T> Stream<List<T>> batches(Iterator<T> source, int length) {
...
}
...
Рейтинг: 0 / 0
25.09.2020, 19:32
    #40002661
Андрей Панфилов
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Разбить list на list из sublist
chpasha
как по мне код слегка не очевиден
Да это что-то странное, а не код:
- никаких гарантий на упорядоченность (на вход же элементы упорядоченно идут)
- никаких гарантий на мутабельность результата

при этом если делать "по классике", то кода там аж 4 строки.
...
Рейтинг: 0 / 0
26.09.2020, 00:09
    #40002740
mayton
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Разбить list на list из sublist
Надо в виде теста сразу писать.

Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
public class PartitionTest {

    static <T> List<List<T>> chopped(List<T> list, final int L) {
        List<List<T>> parts = new ArrayList<List<T>>();
        final int N = list.size();
        for (int i = 0; i < N; i += L) {
            parts.add(new ArrayList<T>(
                    list.subList(i, Math.min(N, i + L)))
            );
        }
        return parts;
    }

    @Test
    public void test() {
        List<String> list = asList("A","B","C","D","E","F","G","H");
        assertEquals(asList(asList("A","B","C"),
                            asList("D","E","F"),
                            asList("G","H")), chopped(list, 3));
    }

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


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