Рекурсивное разбиение строки на фиксированное количество слов [Java] - PullRequest
0 голосов
/ 03 февраля 2020

Я пытаюсь рекурсивно разбить String (хранится в ArrayList) на фиксированное количество слов (не символов).

Например, предположим, у меня есть ArrayList, который содержит следующие две String фразы:

ArrayList<String> words = new ArrayList<String>();
words.add("key1 key2 key3 key4 key5 key6 key7");
words.add("key11 key12 key13 key14 key15 key16 key17");

И я хочу разбить на куски по 5 слов (int desiredListSize = 5;) - это даст следующие два списка:

LIST 1:

word1 word2 word3 word4 word5
word2 word3 word4 word5 word6
word3 word4 word5 word6 word7

LIST 2:

word11 word12 word13 word14 word15
word12 word13 word14 word15 word16
word13 word14 word15 word16 word17

Каждый приведенный выше список будет затем добавлен в массив List of Lists, поэтому выходные данные будут иметь формат: ArrayList<ArrayList<String>()

Так далеко следующий фрагмент кода решает большую часть проблемы:

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import java.util.stream.Stream;

public static void splitListIntoWords()
{

    int desiredListSize = 5;
    final ArrayList<String> textWords = new ArrayList<String>(); 
    textWords.add("key1 key2 key3 key4 key5 key6 key7");
    textWords.add("key11 key12 key13 key14 key15 key16 key17");


    final List<List<String>> listOfLists = textWords.stream().flatMap(w -> {

        final String[] wordList = StringX.splitStrIntoWordsRtrnArr(w); // w.split(" ");

        int calculatedListSize = (wordList.length < desiredListSize) ? wordList.length : desiredListSize;

        return  IntStream.range(0, Math.min(wordList.length - (calculatedListSize - 1), wordList.length)).mapToObj(i -> i ).flatMap(i -> Stream.of(
                IntStream.range(i, Math.min(i+desiredListSize, wordList.length)).mapToObj(j -> wordList[j])
                .collect(Collectors.toList())));
    })          .collect(Collectors.toList());


    for (int counter = 0; counter < listOfLists.size(); counter++) {

        System.out.println("LIST: " + counter);


        System.out.println(listOfLists.get(counter).toString());
    }

}

, который выдает следующий вывод:

LIST: 0
[key1, key2, key3, key4, key5]
LIST: 1
[key2, key3, key4, key5, key6]
LIST: 2
[key3, key4, key5, key6, key7]
LIST: 3
[key11, key12, key13, key14, key15]
LIST: 4
[key12, key13, key14, key15, key16]
LIST: 5
[key13, key14, key15, key16, key17]

Однако идеальный вывод:

LIST 0:
key1 key2 key3 key4 key5
key2 key3 key4 key5 key6
key3 key4 key5 key6 key7

LIST 1: 
key11 key12 key13 key14 key15
key12 key13 key14 key15 key16
key13 key14 key15 key16 key17

Затем оба списка должны быть добавлены к listOfLists.

Обратите внимание, что в желаемом выводе каждый список сохраняет результат операции со строкой: key1 key2 key3 key4 key5 как один String ( с пробелом между каждым словом) НЕ как список .

Другими словами, когда кто-то вызывает listOfLists.get(0); one s должен получить список, который содержит результаты операции на words.add("key1 key2 key3 key4 key5 key6 key7");, а когда вы вызываете listOfLists.get(1);, вы должны получить результаты операции на words.add("key11 key12 key13 key14 key15 key16 key17"); Конечно, если в исходном textWords List больше двух записей, то listOfLists будет содержать соответствующее количество списков.

Спасибо!

1 Ответ

1 голос
/ 04 февраля 2020

ОС У меня сейчас нет времени, чтобы уточнить свои сообщения, но вот лучше (я думаю) оригинальных сообщений. Я могу вернуться завтра когда-нибудь, но у меня есть работа, которую тоже нужно выполнять: -)

В любом случае, вот она:

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import java.util.stream.Stream;

public class StackOverflow {

    public static void main(final String[] args) {

        final List<String> words = new ArrayList<>();
        words.add("key1 key2 key3 key4 key5 key6 key7");
        words.add("key11 key12 key13 key14 key15 key16 key17");

        final List<List<String>> listOfLists = words.stream().flatMap(w -> {

            final String[] wordList = w.split(" ");

            return  IntStream.range(0, Math.min(  3, wordList.length)).mapToObj(i ->          i ).flatMap(i -> Stream.of(
                    IntStream.range(i, Math.min(i+5, wordList.length)).mapToObj(j -> wordList[j])
                    .collect(Collectors.toList())));
        })          .collect(Collectors.toList());

        listOfLists.forEach(System.out::println);
    }
}
...