Separator idiom

R

Roedy Green

Lets say you want to create a list of items separated by something
e.g. comma <BR> \n etc, but you don't want a terminator.

How do you go about constructing it with minimal fuss?
 
A

Andreas Leitgeb

Roedy Green said:
Lets say you want to create a list of items separated by something
e.g. comma <BR> \n etc, but you don't want a terminator.
How do you go about constructing it with minimal fuss?

Iterator<String> it=list.iterator();
while (it.hasNext()) {
System.out.print(it.next());
if (it.hasNext()) System.out.print(sepChar);
}

Less fuss in Tcl: puts [join $list $sepChar]
 
A

Alexander.V.Kasatkin

How do you go about constructing it with minimal fuss?

public static String build(List<?> list, String separator) {
StringBuilder buf = new StringBuilder();
for (Object obj : list) {
if (buf.length() > 0) {
buf.append(separator);
}
buf.append(obj);
}
return buf.toString();
}


BR,
Alex
 
S

Stefan Ram

Roedy Green said:
Lets say you want to create a list of items separated by something
e.g. comma <BR> \n etc, but you don't want a terminator.
How do you go about constructing it with minimal fuss?

Because I do not know the meaning of »fuss«,
I will ignore » with minimal fuss«:

public static java.lang.CharSequence format
( final java.lang.CharSequence[] source )
{ final java.lang.StringBuilder text = new java.lang.StringBuilder();
boolean first = true;
for( final java.lang.CharSequence component : source )
{ if( first )first = false; else text.append( "\n" );
text.append( component ); }
return text; }
 
S

Stefan Ram

Eric Sosman said:
// Treat first item as "special"
System.out.print(array[0]);
for (int i = 1; i < array.length; ++i) {
System.out.print(", ");
System.out.print(array);
}
[...] I actively try to avoid the first.


What I like about it, is that it avoids the run-time overhead
to check the position within the loop.

Two problems with this are: It can not be generalized to loops
with for( ... : ... ), and it needs an additional »if« to be correct:

// Treat first item as "special"
if (array.length > 0) {
System.out.print(array[0]);
for (int i = 1; i < array.length; ++i) {
System.out.print(", ");
System.out.print(array);
}
}
 
M

Mark Space

Stefan said:
What I like about it, is that it avoids the run-time overhead
to check the position within the loop.

It seems like one should be able to generate the sequence as normal,
then shorten the output to remove the last separator. This should be
very efficient, as reducing the size of a buffer or file is almost cost
free.


public String sequence( Object [] obj, String sep ) {

StringBuilder sb = new StringBuilder();
for( Object o : obj ) {
sb.append( o );
sb.append( sep );
}
if( sb.length() >= sep.length() ) {
sb.setLength( sb.length() - sep.length() )
}
return sb.toString();
}

But I'm not seeing a way to make that complete general (I can't find a
way to trim the size of both a StringWriter and a FileWriter. I need
some sort of random access for both. Or at least a way to change the
file length.)
 
D

Daniel Pitts

public static String build(List<?> list, String separator) {
StringBuilder buf = new StringBuilder();
for (Object obj : list) {
if (buf.length() > 0) {
buf.append(separator);
}
buf.append(obj);
}
return buf.toString();
}


BR,
Alex
get apache commons, and use StringUtils.join().
 
D

Daniel Pitts

Roedy said:
Lets say you want to create a list of items separated by something
e.g. comma <BR> \n etc, but you don't want a terminator.

How do you go about constructing it with minimal fuss?
In JSP, I use the varStatus.last or first property.
In Java, if I can't use apache-commons-lang StringUtils, I tend to use:
final StringBuilder out = new StringBuilder();
final Iterator<Foo> it = collection.iterator();
if (it.hasNext()) {
out.append(it.next());
}
while (it.hasNext()) {
out.append(separator);
out.append(it.next());
}

Or, if I'm not concerned with efficiency, which is usually the case:
final StringBuilder out = new StringBuilder();
for (Foo foo: collection) {
if (out.size() != 0) {
out.append(separator);
}
out.append(foo);
}

All of these are pretty standard idioms. Unless you use a utility
method somewhere, I don't think you'll get much smaller than that.

In python I use ", ".join(myStrings) :), although I never use python.
 
R

Roedy Green

Lets say you want to create a list of items separated by something
e.g. comma <BR> \n etc, but you don't want a terminator.

How do you go about constructing it with minimal fuss?
--

I have taken your various suggestions and canonicalised them into 7
methods that all use the same parms and naming conventions. They are
posted at http://mindprod.com/jgloss/separator.html
 
R

Roedy Green

Note that join3() for some input may give different result than the
other methods, for example:

List<String> input = Arrays.asList( "", "X", "" );

join2( input, "|" ) --> "|X|"
join3( input, "|" ) --> "X|"


Note also, that join1() will fail for zero-element list and non-empty
separator input. To correct it trim off the last separator
only when sb.length() > 0.


Oh, and if you're still collecting them, here is another approach:

public static String join(String[] a, String sep) {
StringBuilder sb = new StringBuilder();
if (a.length > 0) {
for (int i = 0;;) {
sb.append(a);
if (++i == a.length) break;
sb.append(sep);
}
}
return sb.toString();
}


I added your method, canonicalised to use the same parms as the
others.

I corrected one of the flaws you discovered. If I corrected the other
flaw it turns into one of the other methods, so I left it as is, just
documented it.

I added two tests to the harness to check your corner cases..

You can see the results at http://mindprod.com/jgloss/separator.html
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,579
Members
45,053
Latest member
BrodieSola

Latest Threads

Top