join array

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
7 messages Options
Reply | Threaded
Open this post in threaded view
|

join array

Sergei Gnezdov
If I have an array of String objects.  How do I join those objects with a
separator?
For example 3 elements (one, two and three) should look like
'one,two,three'.

Here is what I did.  I think it could be simpler:

join: aCollection with: aSeparator
    | joinedString |
    joinedString := String new.
    aCollection do: [:each | joinedString := joinedString , each]
        separatedBy: [joinedString := joinedString , aSeparator
displayString].
    ^joinedString

Thank you


Reply | Threaded
Open this post in threaded view
|

Re: join array

Dmitry Zamotkin-4
Sergei Gnezdov wrote:

> If I have an array of String objects.  How do I join those objects
> with a separator?
> For example 3 elements (one, two and three) should look like
> 'one,two,three'.
>
> Here is what I did.  I think it could be simpler:
>
> join: aCollection with: aSeparator
>     | joinedString |
>     joinedString := String new.
>     aCollection do: [:each | joinedString := joinedString , each]
>         separatedBy: [joinedString := joinedString , aSeparator
> displayString].
>     ^joinedString

Using stream is more readable and faster:

join: aCollection with: aSeparator
| stream |
stream := String new writeStream.

aCollection
    do: [ :string | string printOn: stream ]
    separatedBy: [ aSeparator printOn: stream ].

^ stream contents

I have method for such operations:

Collection>>asStringSeparatedBy: aSeparator
| stream |
stream := String new writeStream.

self
    do: [ :string | string printOn: stream ]
    separatedBy: [ aSeparator printOn: stream ].

^ stream contents

--
Dmitry Zamotkin


Reply | Threaded
Open this post in threaded view
|

Re: join array

Ian Bartholomew-18
In reply to this post by Sergei Gnezdov
Sergei,

> If I have an array of String objects.  How do I join those objects with a
> separator?

Your basic outline is correct but it would be better to use a stream rather
than just concatenating the sub strings as this can get a bit inefficient
for more than three or four strings.

join: aCollectionOfStrings with: aCharacter
    | stream |
    stream := String writeStream.
    aCollectionOfStrings
        do: [:each | stream nextPutAll: each]
        separatedBy: [stream nextPut: aCharacter].
    ^stream contents

Ian


Reply | Threaded
Open this post in threaded view
|

Re: join array

Dmitry Zamotkin-4
Hello Ian!

> join: aCollectionOfStrings with: aCharacter
>     | stream |
>     stream := String writeStream.
>     aCollectionOfStrings
>         do: [:each | stream nextPutAll: each]
>         separatedBy: [stream nextPut: aCharacter].
>     ^stream contents

I suppose #printOn: method is more general. In this case you could use
Character or String (or any other?) asSeparator. And you can join printable
presentations for every object type.

--
Dmitry Zamotkin


Reply | Threaded
Open this post in threaded view
|

Re: join array

Ian Bartholomew-18
Dmitry,

> I suppose #printOn: method is more general. In this case you could use
> Character or String (or any other?) asSeparator. And you can join
> printable presentations for every object type.

Yes, it would make it more general but using #printOn: with String arguments
will then get a bit messy.  For example, using your code (implemented in
Object for convenience)

x := 1 join: #('aaa' 'bbb' 'ccc') with: ','.

sets x to 'aaa'',''bbb'',''ccc'

It can get confusing as if you display the above result as the quotes then
get doubled again but

x size

does answer 21 and not the expected 11 that you would get with aaa,bbb,ccc

Regards
    Ian


Reply | Threaded
Open this post in threaded view
|

Re: join array

Dmitry Zamotkin-4
Hi, Ian!

> Yes, it would make it more general but using #printOn: with String
> arguments will then get a bit messy.  For example, using your code
> (implemented in Object for convenience)

Oops! Sorry, not #printOn: but #displayOn:


--
Dmitry Zamotkin


Reply | Threaded
Open this post in threaded view
|

Re: join array

Ian Bartholomew-18
Dmitry,

> Oops! Sorry, not #printOn: but #displayOn:

Ah yes, I should have realised that is what you meant.

I suppose a "general purpose" method in Collection might be worthwhile if
you do this a lot but, personally, I don't think I would be using it very
often.  I would normally aim to have values that could be added to line in a
csv file as instance variables in a class - not as loose values in a
collection.  It just seems to make it easier if you can have two
corresponding methods ...

anObject writeAsCsvTo: aStream

anObject readAsCsvFrom: aStream

.  in the same class as the data.

I suppose there might be other situations where a #join:with: method might
be useful but, on the other hand, creating a stream inline is quite easy
and, IMHO, more flexible.

Regards
    Ian