Home > Blockchain >  Join list of string with commas and new lines
Join list of string with commas and new lines

Time:10-27

I need to join a list of strings with commas. But also I have a limit of line length. For example list I need to join a list of strings with commas should become : I, need, to, join, a, \n list, of, strings, with, \n commas.

I've already implemented a method for this:

private static String joinLabels(List<String> strings) {
    int rowLengthCounter = 0;
    StringBuilder result = new StringBuilder();
    for (String str : strings) {
        rowLengthCounter  = str.length();
        if (rowLengthCounter > 40) {
            result.append("\n");
            rowLengthCounter = str.length();
        }
        result.append(str);
        result.append(", ");
    }
    return result.substring(0, result.lastIndexOf(", "));
}

And it works. But maybe simple method exists, like String.join to join strings with specified delimiter, or stream API. Thanks for help.

CodePudding user response:

The code is quite complicated with streams but you can write it like that :

    public static String joinLabels2(final List<String> strings,) {
    final Optional<String> res = strings.stream()
            .map(s -> s   ", ")
            .reduce((s1, s2) ->
                    s1.contains("\n") && (s1   s2).length() - StringUtils.lastIndexOf(s1, "\n") > 40
                    ||
                    !s1.contains("\n") && (s1   s2).length() > 40
                    ?
                    s1   s2   "\n" : s1   s2)
            .map(s -> s.substring(0, s.length() - 2));
    return res.get();
}

Test by changing the max length from "40" to "10" :

@Test
public void test() {
    System.out.println(joinLabels2(Arrays.asList("I", "need", "to", "join", "a", "list", "of", "strings", "with", "commas")));
}

outputs :

I, need, to, 
join, a, list, 
of, strings, 
with, commas,

It would be great to write the reduce condition like that : (s1 s2).length() > 40 ? ... but after the first line break the condition would be always true because s1 contains the previous reduction.

NB: you need to fine tune that method if you want to compare the length without commas because I added them before the reduction but you didn't in your original code.

CodePudding user response:

I would do something like this. It eliminates the counter, so that is one less moving part.

  • Add commas to each string except the last one
  • try to add each token to the StringBuilder
    • If adding next token to the the current line in the StringBuilder is more than max, add line break
    • Add token
private static final int maxLength = 15;
private static final List<String> strings = Arrays.asList("I", "need", "to", "join", "a", "list", "of", "strings", "with", "commas");

public static void main(String[] args) {
    StringBuilder sb = new StringBuilder();

    IntStream.range(0, strings.size())
            .mapToObj(i -> strings.get(i)   (i<strings.size()-1 ?  ", " : ""))
            .forEach(s -> addToStringBuilder(s, sb));

    System.out.println(sb);
}

private static void addToStringBuilder(String s, StringBuilder sb) {
    int currentLineLength = sb.length() - sb.lastIndexOf("\n");
    if (currentLineLength   s.length() > maxLength) {
        sb.append("\n");
    }
    sb.append(s);
}

Output:

I, need, to, 
join, a, 
list, of, 
strings, 
with, commas

CodePudding user response:

you can use java 8's stream and collectors api to do like this,

private static String joinLables(List<String> lables) {
    final AtomicInteger counter = new AtomicInteger();
    final Integer chunkSize = 3;
    final String DELIMITER = ",";
    return lables.stream()
            .collect(Collectors.groupingBy(it -> counter.getAndIncrement() / chunkSize)).values()
            .stream()
            .map(s -> String.join(DELIMITER, s))
            .reduce((a, b) -> a   "\n"   b)
            .get();
}
  • Related