SPLIT STRING

Is there a quick command for splitting strings into equal increments?

Ive been using the code below but it does not do well at all.


display dialog my splitText_section("one two three four five six seven", 2)   ----NEEDS FIXED ---  does not work with vety well   on splitText_section(someText, w) -----(string, sections)      set prevTIDs to AppleScript's text item delimiters      set AppleScript's text item delimiters to " "      set output to text items of someText      set AppleScript's text item delimiters to prevTIDs      set output2 to ""      set x to 0      set y to 0      set cnt to count item of output      set partz to cnt / w as string      set partz to round partz rounding up      repeat           set x to x + 1           set output2 to output2 & item x of output as string           set y to y + 1           if y < partz then set output2 to output2 & " "           if x = cnt then exit repeat           if y = partz then                set output2 to output2 & return                set y to 0           end if      end repeat      return output2 end splitText_section

imac, Mac OS X (10.5.8)

Posted on Feb 17, 2010 7:38 AM

Reply
45 replies

Feb 18, 2010 7:54 PM in response to ericmeyers

Is applescript painful... yes indeed!!

Your script is a great way to divide strings in two however when I change the dividing increment to 3, it gives me 4 lines. This is similar to word wrapping.

I need the lines to be as close to equal lengths and with no more paragraphs/lines than the dividing variable.

Sometimes the input variable is short:
"Valley Club"
and sometimes longer:
"The Ohio Valley Longer-word-than-normal Country Club, Casino & Resorts"

I am preparing the string for a design element so I need to utilize maximum space to keep the text legible.

So if I had this longer string and I need it to fit in a tight area in my design with a max height capable of inserting 3 lines of copy then the LOGICAL OUTPUT SHOULD BE:

"The Ohio Valley
Longer-word-than-normal
Country Club, Casino & Resorts"

(max width is handled with the design app)

Something tells me that there is no replacement for the human eye on this problem. Im on my 12th avenue of script techniques.

Feb 19, 2010 9:57 AM in response to ericmeyers

Still got the wrong number of lines when I ran this with dividing by 4.
Also how do i run the ruby script without calling on it from a text file?


[code]
-----the ruby script
set ruby_script to ("def split_me (str,n)
wordcount = str.scan(/[^\\s]+/).size
ms = str.scan /(([^\\s] (\s)?){#{(wordcount.to_f/n).ceil}})/
ms.each do |m|
print \"#{m[0]}
\"
end
end

split me(ARGV[0],ARGV[1].toi)
") as string


---write to temp file
set prefz to (path to desktop) & "temp.rb" as string
open for access file prefz with write permission
set eof of file prefz to 0
write ruby_script to file prefz
close access file prefz

set path toscript to (quoted form of POSIX path of prefz)
set the_string to "'Split This Line Into Two Parts'"
display dialog (do shell script "ruby " & path toscript & " " & the_string & " 4")

tell application "Finder" to delete file prefz

Feb 20, 2010 8:19 AM in response to handellphp

OK handell. I took a different approach to the problem. This time I tried to "optimize" the layout so the minimum amount of "overrage" is found by laying out the words multiple times. The minimum solution is returned.


def split_me (str,n, allowed=0)
wordcount = str.scan(/[^s]+/).size
charcount = str.length
newlinelength = (charcount/n)
lines = []
line = ""
overrages = []
ms = str.scan /([^s](s)?)/
ms.each do |m|
chunk = m[0]
if lines.size == n-1 then
line = line + chunk
elsif (chunk.length+line.length <= (newlinelength+allowed) ) then
line = line + chunk
else
lines << line
overrage = line.length - newlinelength
overrages << overrage if overrage >= 0
line = chunk
end
end
if line != "" then
lines << line
overrage = line.length - newlinelength
overrages << overrage if overrage >= 0
end
[lines,overrages]
end
#
# let's call split_me a number of time allowing for different overrages and try
# to find the minimum actual overrage. thats the one well think looks best
#
def split_opt(str,n)
res = []
lastmin = str.length
charcount = str.length
newlinelength = (charcount.to_f/n).ceil
(0..(newlinelength-1)).each do |i|
lines,overrages = split_me(str,n,i)
# p overrages.min
if overrages.min < lastmin then
res = lines
lastmin = overrages.min
end
end
res
end
res = splitopt(ARGV[0],ARGV[1].toi)
res.each do |r|
print "#{r} "
end



ruby abc.rb 'The Ohio Valley Longer-word-than-normal Country Club, Casino & Resorts' 1
The Ohio Valley Longer-word-than-normal Country Club, Casino & Resorts
ruby abc.rb 'The Ohio Valley Longer-word-than-normal Country Club, Casino & Resorts' 2
The Ohio Valley Longer-word-than-normal
Country Club, Casino & Resorts
ruby abc.rb 'The Ohio Valley Longer-word-than-normal Country Club, Casino & Resorts' 3
The Ohio Valley
Longer-word-than-normal
Country Club, Casino & Resorts
ruby abc.rb 'The Ohio Valley Longer-word-than-normal Country Club, Casino & Resorts' 4
The Ohio Valley
Longer-word-than-normal
Country Club, Casino
& Resorts
ruby abc.rb 'The Ohio Valley Longer-word-than-normal Country Club, Casino & Resorts' 5
The Ohio
Valley
Longer-word-than-normal
Country Club,
Casino & Resorts


You can call ruby from your AppleScript like I've shown you before.

Eric

Feb 21, 2010 12:50 PM in response to handellphp

You can save the ruby script in the contents/resources folder in the application bundle. It's a little messy, but does work. This way you will not have to copy two files to the target system.
I named the applescript file stringDividerV2.app
I named the ruby file stringDivide.rb


mac $ ls -ld /Applications/Applescript\ files/stringDividerV2.app/
drwxr-xr-x 3 mac wheel 102 Feb 21 15:29 /Applications/Applescript files/stringDividerV2.app//
mac $ ls -l /Applications/Applescript\ files/stringDividerV2.app/Contents/Resources/stringDivide.rb
-rw-r--r-- 1 mac wheel 1308 Feb 21 14:50 /Applications/Applescript files/stringDividerV2.app/Contents/Resources/stringDivide.rb


See:
on run
-- Write a message into the event log.
log " --- Starting on " & ((current date) as string) & " --- "
(* path to me doesn't work for me in Script editor in Tiger.
Run as application bundle.
Should work in Tiger, so maybe it was fixed in a later Mac OS

may work better in Smile

If you use save as in script editor for Tiger, your resource will disappear. Re-copy
*)
set path_to_script to (path to me as string) -- & "Contents:Resources:stringDivide.rb"
-- Get around Tiger impletement path to me as path to application, hence
-- script editor
if path_to_script contains "Script Editor" then
log "must be debuggin"
-- You will need to adjust !!!
set path_to_script to (path to applications folder as string)
-- You will need to adjust !!!
set path_to_script to path_to_script & "Applescript files:" & "stringDividerV2.app:"
end if
log "path_to_script= " & path_to_script
set path_to_script to POSIX path of (alias path_to_script)
log "path_to_script= " & path_to_script
set path_to_script to path_to_script & "/Contents/Resources/stringDivide.rb"
(* Not working for me... In tiger 10.4.11 *)
-- set path_to_script to path to resource "stringDivider.rb"
set path_to_script to escapeString(path_to_script)
log "path_to_script= " & path_to_script
set foobar to "'The Ohio Valley Country Club, Casino & Resorts'"
set res to do shell script "ruby " & path_to_script & " " & foobar & " 2"
display dialog res


end run

-- ------------------------------------

on escapeString(thisString)

set thisString to alterString(thisString, "\\", "\\\\")
set thisString to alterString(thisString, " ", "\\ ")
set thisString to alterString(thisString, quote, "\\" & quote)

end escapeString

on alterString(thisText, delim, replacement)
set resultList to {}
set {tid, my text item delimiters} to {my text item delimiters, delim}
try
set resultList to every text item of thisText
set text item delimiters to replacement
set resultString to resultList as string
set my text item delimiters to tid
on error
set my text item delimiters to tid
end try
return resultString
end alterString

Feb 21, 2010 3:33 PM in response to handellphp

Hi,
Something tells me that there is no replacement for the human eye on this problem.

I completely agree with you. Nevertheless, the following script (beta version) seems to return the expected result for each and every example discussed so far in this thread. Please note however that it could not work as well with texts having more than one +extraordinarily longer+ than usual word.

Maybe you would like to try it.

--BEGINNING OF SCRIPT

splitString("one two three four five six extraordinarily_longer", 3) -- for example

on splitString(theText, N)
set theWords to words of theText
set TNW to count theWords -- total number of words
if N < 1 or N > TNW then return "Choose N between 1 and " & TNW & "."

--Provide for one extraordinarily longer word than usual :
set maxWordLength to length of item 1 of theWords
repeat with thisWord in rest of theWords
if length of thisWord > maxWordLength then set maxWordLength to length of thisWord
end repeat
set theLength to length of theText
set L0 to theLength / N -- average length of each line
if L0 < maxWordLength then set L0 to (theLength - maxWordLength) / (N - 1)

set theNewText to ""
set j to 0 -- number of lines
set CNW to 0 -- number of words in the first j lines
repeat (N - 1) times
set j to j + 1
set currentLine to ""
set L to 0 -- length of the current line
set k to 0 -- number of words in the current line
set endOfLine to false
repeat until L > L0
if TNW - CNW - k = N - j then
set endOfLine to true
exit repeat
end if
set k to k + 1
set L to length of (text 1 through word k of theText)
end repeat
if endOfLine then
set k to k + 1
set L to (length of (text 1 through word k of theText)) - (length of (word k of theText))
else
set L to L - (length of (word k of theText))
if L = 0 then
set k to k + 1
set L to (length of (text 1 through word k of theText)) - (length of word k of theText)
else -- Let's see if one more word wouldn't be better :
set k to k + 1
set L2 to (length of (text 1 through word k of theText)) - (length of (word k of theText))
if (L2 - L0) < (L0 - L) then set L to L2
end if
end if
set currentLine to text 1 through L of theText
set theText to text (L + 1) through -1 of theText -- the rest of the text
set CNW to CNW + (count words of currentLine)
set theNewText to theNewText & currentLine & character id 8232 -- end of line
end repeat

return theNewText & theText -- add the last line
end splitString

--END OF SCRIPT

Hope it can help.

Feb 22, 2010 4:46 AM in response to ericmeyers

PERFECT enough.


HOWEVER WHEN I RUN:
ruby abc.rb 'Split This Line Into Variable Yet Close to Equal Parts Limiting to certain number of lines' 4

RESULT:
'Split This Line Into
Variable Yet Close to
Equal Parts Limiting
to certain number of lines'


WHEN:
'Split This Line Into
Variable Yet Close to
Equal Parts Limiting to
certain number of lines'

WOULD BE A THE LOGICAL SOLUTION.


I think Ill use this one.
THANKS A MILLION ERIC.

Message was edited by: handellphp

Feb 22, 2010 4:58 AM in response to Pierre L.

Also very nice indeed Pierre.


HOWEVER WHEN I RUN:
splitString("Split This Line Into Variable Yet Close to Equal Parts Limiting to certain number of lines", 4) -- for example

I GET
RESULT:
'Split This Line Into
Variable Yet Close to
Equal Parts Limiting
to certain number of lines'

WHEN:
'Split This Line Into
Variable Yet Close to
Equal Parts Limiting to
certain number of lines'

WOULD BE A THE LOGICAL SOLUTION.



Its almost as if I need to work on a follow up function to compare the outcome of the split string function. This would entail somehow to compare the character counts of each line with & without adding the last word of previous line & first word of next line. Then each current line with its temporarily added word cannot be greater previous or next line else a word shift would take place and the function becomes recursive.

(again my goal is design oriented and is aimed to please the customers eye, anything that looks funny usually gets rejected)

This thread has been closed by the system or the community team. You may vote for any posts you find helpful, or search the Community for additional answers.

SPLIT STRING

Welcome to Apple Support Community
A forum where Apple customers help each other with their products. Get started with your Apple Account.