How to replace just the first found space with tab for all lines in a variable?

Alex Tweedly alex at tweedly.net
Thu May 26 06:32:53 EDT 2011


On 25/05/2011 16:48, Nonsanity wrote:
> And if this is a one-shot utility function, than any of these solutions that
> work for you are great. But if you will be doing this as a feature of a
> program, and the amounts of data you'll be pushing through are large, then
> modifying the data in-place saves time and memory over copying large
> quantities of text between two variables. Just sayin'. :)
That's true - in general, but not in this case.

The big exception is that "line a of myText" is quite expensive in LC. 
In fact, it is VERY expensive, because the engine needs to scan the text 
to find the line, which means that operations such as

>     repeat with a = 1 to the number of lines in myText
>        if space is not in line a of myText then next repeat
>        put tab into char (offset( space, line a of myText )) of line a of myText
>     end repeat
take time based on the square of the number of chars/lines in the data.

On the other hand, copying from one variable to another takes linear 
time based on the number of chars/lines, and

repeat for each line L in myText
     ...
     put theModifiedLine & CR after tOutputData
end repeat

is also linear (so long as it is "put xxx *after* tOutputData" because 
simply appending is linear).

So, taking the benchmark that Jim recently sent, and adding the 
alternative version which modifes it in place, we see that modifying in 
place is very, very slow by comparison.

On my Macbook Pro, the "copy" method takes 1 tick while the "in place" 
version takes around 820 (btw - I changed the number of lines down to 
20000; estimated time for the original count would have been too slow).

--- working code ----
on mouseUp
    trythisForSpeed
end mouseUp


on trythisForSpeed

    put 20000 into weaponOfMassConstruction

    repeat weaponOfMassConstruction times
       get the seconds
       put IT && IT && IT & cr after massiveList
    end repeat

    put the ticks into startt
    repeat for each line tLine in massiveList
       put word 1 of tLine&  tab&  word 2 to -1 of tLine&  return after 
tResultTable
    end repeat
    filter tResultTable without empty

    put the ticks - startt into elapsedTks
    if elapsedTks = 0 then
       put "Too fast to measure 'cause it took less than 1 tick" & CR
    else
       put "elapsed =" && elapsedTks && "ticks thus" \
&& elapsedTks/60 && "seconds" & cr \
&& "or" && weaponOfMassConstruction/elapsedTks \
&& "address lines per tick" & cr \
&& "or approx" \
&& 60*(weaponOfMassConstruction/elapsedTks) \
&& "per second" & CR

    end if

    put the ticks into startt
    repeat with I = 1 to the number of lines in massiveList
       -- if space is not in line I of myText then next repeat
       put tab into char (offset( space, line I of massiveList )) of 
line I of massiveList
    end repeat

    put the ticks - startt into elapsedTks
    if elapsedTks = 0 then
       put "Too fast to measure 'cause it took less than 1 tick" & CR 
after msg
    else
       put "elapsed =" && elapsedTks && "ticks thus" \
&& elapsedTks/60 && "seconds" & cr \
&& "or" && weaponOfMassConstruction/elapsedTks \
&& "address lines per tick" & cr \
&& "or approx" \
&& 60*(weaponOfMassConstruction/elapsedTks) \
&& "per second" & CR after msg

    end if

end trythisForSpeed



More information about the use-livecode mailing list