Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Joining collector: possibility to specify custom delimiter used before the last stream element #21

Open
amaembo opened this issue Nov 13, 2015 · 2 comments

Comments

@amaembo
Copy link
Owner

amaembo commented Nov 13, 2015

A custom delimiter could be specified to format more user-friendly messages like this:

StreamEx.of("Red", "Green", "Blue", "Black").collect(
         Joining.with(", ").lastDelimiter(" or "));
// Produces "Red, Green, Blue or Black"

Possible names for new method: lastDelimiter, beforeLast. An open question is whether it should be used when short-circuit occurs.

@numeralnathan
Copy link

numeralnathan commented Oct 28, 2016

A work around for this is...

StreamEx.
   of("Red", "Green", "Blue", "Black").
   collect(Joining.with(", ").lastDelimiter(" or ")).
   replaceFirst("^(.+), (.*)$", "$1 or $2");

The first group in the regular expression is greedy and will try to match the whole string. It will then have to backup until the ", " is found. Thus, the last ", " will be found and replaced with " or ".

This regular expression assumes that ", " will not appear in any of the strings being joined.

@amaembo
Copy link
Owner Author

amaembo commented Oct 29, 2016

@nathanila, actually Joining collector is much more smart. For example, it can short-circuit based on maximal string length, cutting at character/codepoint/grapheme/word bound, etc. It's actually the hardest part here: how to properly combine this lastDelimiter feature with all the existing features. Replacing last delimiter with ", " with " or " may increase the line length exceeding the maximal allowed length. Also it's not semantically equivalent even without length limit. Consider the following input:

List<String> movies = asList("Snatch", "Revolver", "Locks, Stocks and Two Smoking Barrels");
System.out.println("Which movie do you want to see: "+
    StreamEx.of(movies).map(m -> '"'+m+'"').collect(
        Joining.with(", ").lastDelimiter(" or "))+"?");

I mean if the string contains the delimiter, the regexp will screw the things up. In general regexps should be used with caution: with unexpected input (unintentional or malicious) they may break your program.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants