Page 1 of 1

Changing the lines of a string using a repeat loop

Posted: Sat Oct 10, 2020 11:03 am
by MichaelBluejay
What's the best way to iterate over the lines of a string, editing those lines, and having the original string reflect those edits?

Examples will use this string, "s":

30 50 20
40 60 90
45 25 80

i.e.: put "30 50 20" &return& "40 60 90" &return& "45 25 80" into s


"repeat for each" doesn't change the original container

Code: Select all

repeat for each line theLine in s
   put word 1 of theLine -1 into word 1 of theLine
   put word 2 of theLine +2 into word 2 of theLine
   put word 3 of theLine *3 into word 3 of theLine
end repeat
answer s // Returns the original string, 30 50 20...

"repeat with" changes the original container, but we don't get to use the nice "repeat for each" syntax, and our code gets verbose

Code: Select all

repeat with i = 1 to the number of lines of s
      put (word 1 of line i of s) -1 into word 1 of line i of s // parentheses are unnecessary, just for readability
      put (word 2 of line i of s) +2 into word 2 of line i of s
      put (word 3 of line i of s) *3 into word 3 of line i of s
end repeat
answer s // Returns 29, 52, 60...

Combination of the above two methods

Code: Select all

put 1 into i
   repeat for each line theLine in s
      put (word 1 of theLine) -1 into word 1 of line i of s // parentheses are unnecessary, just for readability
      put (word 2 of theLine) +2 into word 2 of line i of s
      put (word 3 of theLine) *3 into word 3 of line i of s
      add 1 to i
   end repeat
answer s // Returns 29, 52, 60...

Build a new string based on the changes

Code: Select all

repeat for each line theLine in s
   put word 1 of theLine -1 into word 1 of theLine
   put word 2 of theLine +2 into word 2 of theLine
   put word 3 of theLine *3 into word 3 of theLine
   put theLine & return after newString
end repeat
answer newString // Returns 29, 52, 60...

There are probably other ways.

How do you all handle this?

Re: Changing the lines of a string using a repeat loop

Posted: Sat Oct 10, 2020 11:21 am
by Klaus
Hi Michael,

yo, "repeat for each..." is insanely fast, but READ ONLY!
Means the container does not change in any way, no matter what you (try) to do in the loop.
The trick is to create a new container with the repeat for each! :D

Code: Select all

...
 put "30 50 20" & return & "40 60 90" & return & "45 25 80" into s
   repeat for each line theLine in s
      put EMPTY into s2
      put word 1 of theLine -1 into s2
      put " " & (word 2 of theLine + 2) after s2
      put " " & (word 3 of theLine * 3) after s2
      put s2 & CR after tNewString
   end repeat
   ## Get rid of trailing CR
   delete char -1 of tNewString
   answer tNewString // Returns the exspected result
...
Best

Klaus

Re: Changing the lines of a string using a repeat loop

Posted: Sat Oct 10, 2020 11:33 am
by MichaelBluejay
Yeah, I said all that.

Re: Changing the lines of a string using a repeat loop

Posted: Sat Oct 10, 2020 11:41 am
by Klaus
Oops, sorry. :oops:

Well, yes, that is all one can say about this topic...

Re: Changing the lines of a string using a repeat loop

Posted: Sat Oct 10, 2020 11:51 am
by MichaelBluejay
I'm surprised that I covered all the bases. I thought there have to be other common method(s) than what I came up with.

Re: Changing the lines of a string using a repeat loop

Posted: Sat Oct 10, 2020 11:54 am
by Klaus
The most common way is in fact to create a new container.
This is still much faster than using "repeat with i =..."

Re: Changing the lines of a string using a repeat loop

Posted: Sat Oct 10, 2020 2:24 pm
by dunbarx
Michael.

I am confused. You have indeed worked the mechanics of several variants of "repeat". But what did you want from the original string in the first place, , that you did not already examine?

For example, if you wanted to double the value of the first word in each line using "repeat for each":

Code: Select all

on mouseUp
   put "30 50 20" & return & "40 60 90" & return & "45 25 80" into s -- create the entire string
   
   repeat for each line tLine in s
      put word 1 of tLine * 2 into word 1 of tLine --IS THIS WHAT YOU MEANT BY EDITING EACH LINE?
      put tLine & return after newS
   end repeat
end mouseUp
But you have to create a new variable to "save" your results.

But what I would have done is this:

Code: Select all

on mouseUp
   put "30 50 20" &return& "40 60 90" &return& "45 25 80" into s
   
   repeat with y = 1 to the number of lines of s
      put word 1 of line y of s * 2 into word 1 of line y of s
   end repeat
end mouseUp
This works the variable "s' directly, as you posted.
Craig

Re: Changing the lines of a string using a repeat loop

Posted: Sat Oct 10, 2020 4:14 pm
by MichaelBluejay
I thought there might be other ways of handling the problem, and there might be a best practice.

Your example #2 is pretty much my example #2.

Re: Changing the lines of a string using a repeat loop

Posted: Sun Oct 11, 2020 2:23 am
by dunbarx
Your example #2 is pretty much my example #2.
Yep:

Code: Select all

...directly, as you posted.
It seems to me that a repeat of some kind is absolutely necessary. Was there something else in the language you thought might be more effective or compact? Or was there something about a repeat construct in general that you thought was either inefficient or poorly applicable?

Craig

Re: Changing the lines of a string using a repeat loop

Posted: Sun Oct 11, 2020 11:07 am
by MichaelBluejay
Obviously a repeat will be necessary, but as I posted, there are at least four ways to use a repeat to solve the problem. I thought there might be other ways, or that one of the four ways I posted was preferred.

Re: Changing the lines of a string using a repeat loop

Posted: Sun Oct 11, 2020 1:56 pm
by stam
Klaus wrote:
Sat Oct 10, 2020 11:21 am
"repeat for each..." is insanely fast, but READ ONLY!

Ah that explains the weirdness I’ve been dealing with ;)
I also had to create new container in the for reach loop but now I understand why :D

Re: Changing the lines of a string using a repeat loop

Posted: Sun Oct 11, 2020 2:23 pm
by dunbarx
Just to be clear, what Klaus meant by "read only" is that the original container, perhaps a field or variable, cannot be changed when using "repeat for each". However, the chunks extracted from that container can indeed be, as I mentioned in:

Code: Select all

on mouseUp
   put "30 50 20" & return & "40 60 90" & return & "45 25 80" into s -- create the entire string
   
   repeat for each line tLine in s
      put word 1 of tLine * 2 into word 1 of tLine --modify tLine here
      put tLine & return after newS
   end repeat
end mouseUp
But such a change in each instance has to be stored somewhere else.

"Repeat with..." can alter the source container directly in each pass.

Craig