Interleaving strings

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

Interleaving strings

Andy Burnett
I have two strings, which are typically of different lengths, and I want to interleave them, i.e.:

'abcdefg' interleaveWith: '123'

Would produce

'a1b2c3defg'

I know how to write this procedurally, but I have been very impressed by what Sven shows in his Medium articles, so I wondered if there is any existing mechanism that would allow me to solve this elegantly?  with:collection: almost does it, but the collections have to be the same size.

Cheers
Andy
Reply | Threaded
Open this post in threaded view
|

Re: Interleaving strings

Nicolai Hess-3-2
What is your implementation with with:collection: ?

I know this function from python, they  call it "zip"

we could implement this in SequenceableCollection

SequenceableCollection>>zip: aCollection
    | index |
    index := 0.
    self size > aCollection size ifTrue:[ ^ aCollection zip: self].
    ^ self class new: (aCollection size + self size) streamContents: [:stream |
            aCollection
                do: [:each | index:=index + 1. stream nextPut: each ]
                separatedBy: [(index > self size) ifFalse:[stream nextPut: (self at:index) ]]]

Another example, using a generator (I didn't used Generator before, but I like the
idea to create an endless stream from a string, with some fill value (empty string in this case)).

|gen|
gen := Generator on:[:g |  '123' do:[:k | g yield: k asString ] . [true] whileTrue:[g yield:'']].
String streamContents:[:stream |
    'abcdefg' do:[:c | stream nextPut: c]
    separatedBy:[ stream nextPutAll:gen next]]



2016-03-15 2:09 GMT+01:00 Andy Burnett <[hidden email]>:
I have two strings, which are typically of different lengths, and I want to interleave them, i.e.:

'abcdefg' interleaveWith: '123'

Would produce

'a1b2c3defg'

I know how to write this procedurally, but I have been very impressed by what Sven shows in his Medium articles, so I wondered if there is any existing mechanism that would allow me to solve this elegantly?  with:collection: almost does it, but the collections have to be the same size.

Cheers
Andy

Reply | Threaded
Open this post in threaded view
|

Re: Interleaving strings

hernanmd


2016-03-21 17:43 GMT-03:00 Nicolai Hess <[hidden email]>:
What is your implementation with with:collection: ?

I know this function from python, they  call it "zip"

we could implement this in SequenceableCollection

SequenceableCollection>>zip: aCollection
    | index |
    index := 0.
    self size > aCollection size ifTrue:[ ^ aCollection zip: self].
    ^ self class new: (aCollection size + self size) streamContents: [:stream |
            aCollection
                do: [:each | index:=index + 1. stream nextPut: each ]
                separatedBy: [(index > self size) ifFalse:[stream nextPut: (self at:index) ]]]

Another example, using a generator (I didn't used Generator before, but I like the
idea to create an endless stream from a string, with some fill value (empty string in this case)).

|gen|
gen := Generator on:[:g |  '123' do:[:k | g yield: k asString ] . [true] whileTrue:[g yield:'']].
String streamContents:[:stream |
    'abcdefg' do:[:c | stream nextPut: c]
    separatedBy:[ stream nextPutAll:gen next]]



I use those all the time (filling matrices etc).
It would be nice to have something like these:

'2' repeatJoin: 4  ==> '2222'
2 repeatJoin: 4 ==> 2222
'2' repeat: 4 ==> #('2' '2' '2' '2')
2 repeat: 4 ==> #(2 2 2 2)

What do you think?

Hernán