Split String into Fixed Number of Words Recursively [Java]

冷暖自知 提交于 2020-03-04 18:43:25

问题


I am attempting to split a String (stored in ArrayList) into fixed number of words (not characters) recursively.

For example, suppose I have the an ArrayList which contains the following two String phrases:

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

And I want to split into chunks of 5 words (int desiredListSize = 5;) - this would produce the following two lists:

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

Each list above would then be added to List of Lists array so the output would be in format: ArrayList<ArrayList<String>()

So far the following code fragment solves most of the problem:

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());
    }

}

Which produces the following output:

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]

However the ideal output is:

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

Both lists above should then be added to listOfLists.

Notice how in the desired output each list stores the result of operation on String: key1 key2 key3 key4 key5 as a single String (with a space between each word) NOT as a list.

In other words, when one calls listOfLists.get(0); one should obtain a list that contains the results of operation on words.add("key1 key2 key3 key4 key5 key6 key7"); and when one calls listOfLists.get(1); one should obtain results of operation on words.add("key11 key12 key13 key14 key15 key16 key17"); Of course, if there's more than two entries in original textWords List then listOfLists will contain a corresponding number of lists.

Thanks!


回答1:


O.S. I don't have time right now to refine my posting, but here's the better (I think) of the original postings. I may get back tomorrow sometime, but I've got a job that needs doing too :-)

Anyway, here it is:

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);
    }
}


来源:https://stackoverflow.com/questions/60032231/split-string-into-fixed-number-of-words-recursively-java

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!