Question

I've created a subclass of Array and written some messages for it that have worked out well so far. However, I'm now having trouble with my last message Here's the body of my code:

startString: charToTest
"Returns a list of all the words that start with a given character"
|  toReturn i j numWords |
i:= 1.
j:= 1.
numWords := 0.
[i <= self size.] whileTrue: [
    (((self at: i) at: 1) = charToTest)
        ifTrue: [numWords := numWords + 1].
    i:= i+1.
].
toReturn := MyArray new: numWords.
i := 1. 
[i <= numWords.] whileTrue: [
    (((self at: i) at: 1) = charToTest)
        ifTrue: [toReturn at: j put: (self at: i). j := j+1].
    i := i + 1.
].
^toReturn

So, essentially, the method looks at itself and creates a new array the size of the number of words that start with the character. It then iterates through again, and puts these words into a new array which it Returns. My workspace looks exactly like this:

|freshArray testArray|
freshArray := MyArray new: 5.
freshArray
    at: 1 put: 'some';
    at: 2 put: 'things';
    at: 3 put: 'are';
    at: 4 put: 'simple';
    at: 5 put: 'things'.
testArray := freshArray startString: $s

When I select this code in my workspace and print it, the method is almost correct. But not quite. For some reason the second slot in "toReturn" isn't filled. The output looks like:

 a MyArray('some' nil)

Why is this happening? Am I separating my statements correctly in the second iterative loop after the if statement? I'm genuinely confused as to what I've been doing wrong. Any help would be appreciated!

Was it helpful?

Solution

Your first iteration counts the number of words that start with the given character (which assumes that the Strings aren't empty, but well you can include a check for that later). So far so good. The second time you're using that count (numWords) to iterate over the array again though - which means that only the words that are in the first 'numWords' slots of the initial array are even considered.

(You may also want to consider replacing your whiles with do: aBlock - that's much less messy and more Smalltalk-y)

OTHER TIPS

We tend to use more compact forms:

testArray := freshArray select: [:each | charToTest = each first ]

Please note that this fails if you have empty strings in the input

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top