Tuesday, September 26, 2017

#1 2017-08-02 05:02:23 pm

Prescience
Member
From:: United Kingdom
Registered: 2017-02-03
Posts: 43

Automatically Create One line from multiple lines of input

I have the following code to take a long list of items, and create a single line of output separated by commas, which are wrapped at the start and end by braces. The code works with two issues that I cannot figure out how to remove.

The first issue, is insertion of double quote marks before and after the new line of output, which I can remove manually, but would like to remove automatically, or not have included in the first instance.

The second issue, is that each text item is wrapped in single quote marks and I would like this to be double quote marks.

I have also noticed that the code changes It's to It'\\''s when run.  Anything inside the list of items should not be changed, such as it's or http:// etc, if possible.

Below the code example is the output it delivers, and an example of what I am trying to achieve.

Can anyone help?

Applescript:



set myString to "
Test1
Test2
Test3
Test4
Test5
Test6
Test7
"


set myList to paragraphs of myString

set listCount to count myList
repeat with i from 1 to my listCount
   set item i of myList to quoted form of item i of myList
end repeat

set {TID, text item delimiters} to {text item delimiters, ", "}
set newString to ("{" & myList as text) & "}"
set text item delimiters to TID

return newString

Output from the current code above is:

"{'Test1 ', 'Test2 ', 'Test3 ', 'Test4 ', 'Test5 ', 'Test6 ', 'Test7'}"



Desired output is to remove the double quote marks at the start and end of the string, and replace the single quote marks around each text item, with double quote marks, as shown below.

{"Test1 ", "Test2 ", "Test3 ", "Test4 ", "Test5 ", "Test6 ", "Test7"}

Last edited by Prescience (2017-08-02 05:40:23 pm)


Wisdom is knowing the power of experience, understanding the knowledge learnt on your personal journey through time, and having the empathy to share with others.

Offline

 

#2 2017-08-02 06:05:51 pm

haolesurferdude
Member
Registered: 2010-02-19
Posts: 104

Re: Automatically Create One line from multiple lines of input

There were two extra "return" characters in your data set.  One at the very top (the return after the first ") and one at the very bottom (the return just before the last ").  I deleted these.  Then a little reworking of the code so that you accumulated your items in a string and it works pretty well.

Applescript:


set myString to "Test1
Test2
Test3
Test4
Test5
Test6
Test7"


set myList to paragraphs of myString
set newString to "" as text

set listCount to count myList

repeat with i from 1 to listCount
   if i = 1 then set newString to "{" as text
   if i < listCount then
       set newString to newString & "'" & item i of myList & "', " as text
   else
       set newString to newString & "'" & item i of myList & "'}" as text
   end if
end repeat

display dialog newString

Offline

 

#3 2017-08-03 02:42:41 am

StefanK
Member
From:: St. Gallen, Switzerland
Registered: 2006-10-21
Posts: 11481
Website

Re: Automatically Create One line from multiple lines of input

This is a solution similar to yours. Instead of adding single quotes it removes the empty lines in the repeat loop.

Applescript:


set myString to "
Test1
Test2
Test3
Test4
Test5
Test6
Test7
"


set myList to paragraphs of myString
set trimmedList to {}
repeat with anItem in myList
   if (count anItem) > 0 then set end of trimmedList to contents of anItem
end repeat

set {TID, text item delimiters} to {text item delimiters, "\", \""}
set newString to ("{\"" & trimmedList as text) & "\"}"
set text item delimiters to TID

display dialog newString


regards

Stefan

Offline

 

#4 2017-08-03 09:15:44 am

haolesurferdude
Member
Registered: 2010-02-19
Posts: 104

Re: Automatically Create One line from multiple lines of input

Stefan,

I checked the time of each of our solutions running them in a repeat loop of 10,000 times.  The result was that the non-TID solution was 51% faster.  I've always wanted to see if using TID was faster than a simple brute force solution like mine.  Thank you for your shorter and more elegant solution.  I learn a great deal from you. Thank you.

Corrected version that produces double quoted output.

Applescript:


set myString to "Test1
Test2
Test3
Test4
Test5
Test6
Test7"


set myList to paragraphs of myString
set newString to "" as text

set listCount to count myList

repeat with i from 1 to listCount
   if i = 1 then set newString to "{" as text
   if i < listCount then
       set newString to newString & "\"" & item i of myList & "\", " as text
   else
       set newString to newString & "\"" & item i of myList & "\"}" as text
   end if
end repeat

display dialog newString

Offline

 

#5 2017-08-03 10:32:33 am

StefanK
Member
From:: St. Gallen, Switzerland
Registered: 2006-10-21
Posts: 11481
Website

Re: Automatically Create One line from multiple lines of input

@haolesurferdude: Your comparison is a bit unfair because you removed the leading and trailing newline characters. wink

If you are interested in speed try this AppleScriptObjC version

Applescript:


use AppleScript version "2.4" -- Yosemite (10.10) or later
use scripting additions

use framework "Foundation"

set myString to "
Test1
Test2
Test3
Test4
Test5
Test6
Test7
"


set cocoaString to current application's NSString's stringWithString:myString
set trimmedString to cocoaString's stringByTrimmingCharactersInSet:(current application's NSCharacterSet's whitespaceAndNewlineCharacterSet)
set newString to ("{\"" & (trimmedString's stringByReplacingOccurrencesOfString:linefeed withString:"\", \"") as text) & "\"}"

display dialog newString

The script assumes linefeed as line separator. If the line separator could change this line considers return and linefeed

Applescript:


set newString to ("{\"" & (trimmedString's stringByReplacingOccurrencesOfString:"[\\n\\r]" withString:"\", \"" options:(current application's NSRegularExpressionSearch) range:{location:0, |length|:trimmedString's |length|()}) as text) & "\"}"

Last edited by StefanK (2017-08-03 10:56:07 am)


regards

Stefan

Offline

 

#6 2017-08-03 10:51:17 am

Yvan Koenig
Member
Registered: 2006-09-14
Posts: 3194

Re: Automatically Create One line from multiple lines of input

@ haolesurferdude

I brought some changes to your proposal :

Applescript:


set myString to "Test1
Test2
Test3
Test4
Test5
Test6
Test7"


set myList to paragraphs of myString
set newString to "{"
repeat with anItem in myList
   set newString to newString & "\"" & anItem & "\", "
end repeat
set newString to (text 1 thru -3 of newString) & "}"

display dialog newString

Yvan KOENIG running Sierra 10.12.6 in French (VALLAURIS, France) jeudi 3 aout 2017 17:51:11

Offline

 

#7 2017-08-03 12:07:17 pm

Yvan Koenig
Member
Registered: 2006-09-14
Posts: 3194

Re: Automatically Create One line from multiple lines of input

StefanK wrote:

@haolesurferdude: Your comparison is a bit unfair because you removed the leading and trailing newline characters. wink



Other point :
in message #1, every string ended with a space character.
in messages #2 and #4 the space characters are gone.
What is the real source and what is the real result wanted ?

I'm wondering if it would be useful to code :

Applescript:

set myString to "
Test1
Test2
Test3
Test4
Test5
Test6
Test7
"

set myList to my decoupe(myString, {space & return, space & linefeed, return, linefeed})
if item 1 of myList is "" then set myList to rest of myList
if item -1 of myList is "" then set myList to items 1 thru -2 of myList
set newString to "{"
repeat with anItem in myList
   set newString to newString & "\"" & anItem & "\", "
end repeat
set newString to (text 1 thru -3 of newString) & "}"

display dialog newString

#=====

on decoupe(t, d)
   local oTIDs, l
   set {oTIDs, AppleScript's text item delimiters} to {AppleScript's text item delimiters, d}
   set l to text items of t
   set AppleScript's text item delimiters to oTIDs
   return l
end decoupe

#=====

Yvan KOENIG running Sierra 10.12.6 in French (VALLAURIS, France) jeudi 3 aout 2017 19:06:28

Offline

 

#8 2017-08-03 01:08:58 pm

Marc Anthony
Member
From:: Dallas, TX
Registered: 2006-04-27
Posts: 765

Re: Automatically Create One line from multiple lines of input

If the blank lines and spaces are not needed, another fast option is to just hack the error message, as the conversion to quoted items has already occurred.

Applescript:

"
Test1
Test2
Test3
Test4
Test5
Test6
Test7
"
's words

try
   display dialog result --can't work
on error Err
   display dialog Err's text 12 thru -19
end try

Offline

 

#9 2017-08-03 02:34:05 pm

Yvan Koenig
Member
Registered: 2006-09-14
Posts: 3194

Re: Automatically Create One line from multiple lines of input

Marc Anthony wrote:

If the blank lines and spaces are not needed, another fast option is to just hack the error message, as the conversion to quoted items has already occurred.

Applescript:

"
Test1
Test2
Test3
Test4
Test5
Test6
Test7
"
's words

try
   display dialog result --can't work
on error Err
   display dialog Err's text 12 thru -19
end try



I'm not sure that it's a good idea.
When I run your code in France, I get :
display dialog "de convertir {\"Test1\", \"Test2\", \"Test3\", \"Test4\", \"Test5\", \"Test6\", \"Test7"

A cleaner version would be :

Applescript:

"
Test1
Test2
Test3
Test4
Test5
Test6
Test7
"
's words

try
   display dialog result --can't work
on error Err
   set theBundle to ((path to library folder from system domain as text) & "Components:AppleScript.component:Contents:Resources:") as «class furl»
   set theKey to "Can't make %1 into type $2."
   set ErrMsg_loc to localized string theKey from table "Localizable" in bundle theBundle
   # 4 added instructions
   if ErrMsg_loc = theKey then # In 10.9, theKey doesn't end with "$2." but with "%2."
       set theKey to "Can't make %1 into type %2." # used by 10.9
       set ErrMsg_loc to localized string theKey from table "Localizable" in bundle theBundle
   end if
   
   --> "Impossible de convertir %1 en type $2."
   log Err
   set theDelims to items 1 thru 2 of my decoupe(ErrMsg_loc, {"%1", "$2"}) --> {"Impossible de convertir ", " en type "}
   log theDelims
   display dialog item 2 of my decoupe(Err, theDelims)
end try

#=====

on decoupe(t, d)
   local oTIDs, l
   set {oTIDs, AppleScript's text item delimiters} to {AppleScript's text item delimiters, d}
   set l to text items of t
   set AppleScript's text item delimiters to oTIDs
   return l
end decoupe

#=====

But I would not rely upon it because it would fail if one or some of the strings contain space characters.

Applescript:

"
My Test1
The Test2
Test 3
Test4
Test5
Test6
Test7
"
's words
#…

would issue : display dialog "{\"My\", \"Test1\", \"The\", \"Test2\", \"Test\", \"3\", \"Test4\", \"Test5\", \"Test6\", \"Test7\"}" which is far from what is wanted.

Yvan KOENIG running Sierra 10.12.6 in French (VALLAURIS, France) jeudi 3 aout 2017 21:33:06

Last edited by Yvan Koenig (2017-08-04 03:45:50 am)

Offline

 

#10 2017-08-03 03:17:09 pm

Marc Anthony
Member
From:: Dallas, TX
Registered: 2006-04-27
Posts: 765

Re: Automatically Create One line from multiple lines of input

Yvan Koenig wrote:


I'm not sure that it's a good idea.



Yes, it probably isn't—at least from a bulletproof use perspective—but I did note that it was a hack for speed. wink It's not particularly important to me, but, rather than a list, your improvement only returns the lone word "string." on my US English system.

Offline

 

#11 2017-08-03 03:32:36 pm

Yvan Koenig
Member
Registered: 2006-09-14
Posts: 3194

Re: Automatically Create One line from multiple lines of input

Marc Anthony wrote:


It's not particularly important to me, but, rather than a list, your improvement only returns the lone word "string." on my US English system.



Puzzling, when I urge my iMac to run in English, I get this history :

Applescript:

tell application "Script Editor"
   display dialog {"Test1", "Test2", "Test3", "Test4", "Test5", "Test6", "Test7"}
       --> error number -1700 from {"Test1", "Test2", "Test3", "Test4", "Test5", "Test6", "Test7"} to string
end tell
tell current application
   path to library folder from system domain as text
       --> "SSD 500:System:Library:"
   localized string "Can't make %1 into type $2." from table "Localizable" in bundle file "SSD 500:System:Library:Components:AppleScript.component:Contents:Resources:"
       --> "Can’t make %1 into type $2."
   (*Can’t make {"Test1", "Test2", "Test3", "Test4", "Test5", "Test6", "Test7"} into type string.*)
   (*Can’t make , into type *)
end tell
tell application "Script Editor"
   display dialog "{\"Test1\", \"Test2\", \"Test3\", \"Test4\", \"Test5\", \"Test6\", \"Test7\"}"
       --> {button returned:"OK"}
end tell

Yes, I added two log instructions to show the components at work.

May you post the history issued on your side ?
No need to hurry, it's late, I will be back tomorrow.

Yvan KOENIG running Sierra 10.12.6 in French (VALLAURIS, France) Thursday, 3 August 2017 22:26:09

Offline

 

#12 2017-08-03 05:25:16 pm

haolesurferdude
Member
Registered: 2010-02-19
Posts: 104

Re: Automatically Create One line from multiple lines of input

I'm so glad all of you found this as interesting as I did.

Thank you everyone!

Offline

 

#13 2017-08-03 05:29:56 pm

Marc Anthony
Member
From:: Dallas, TX
Registered: 2006-04-27
Posts: 765

Re: Automatically Create One line from multiple lines of input

My log is similar to yours—the HD name being the only difference through the localized string portion. It diverges at the point of your logged entry:

tell application "AppleScript Editor"
	display dialog "string."
		--> {button returned:"OK"}
end tell
Result:
{button returned:"OK"}

The code on my machine appears to be returning your first logged line, specifically text -7 thru -1. Perhaps it's a version difference? I'm using Mavericks.

Offline

 

#14 2017-08-04 03:50:09 am

Yvan Koenig
Member
Registered: 2006-09-14
Posts: 3194

Re: Automatically Create One line from multiple lines of input

Got it. In Mavericks, the key pointing to the message used is different than the one in recent systems.

This old key is "Can't make %1 into type %2." (which doesn't match the "official" rules)
Now it's "Can't make %1 into type $2." (which matches the "official" rules)

When you execute the script, as it asked for the new key, ErrMsg_loc  is set to this new key.
ErrMsg_loc is theKey which is "Can’t make %1 into type $2."
theDelims is {"Can't make ", " into type "} with a straight single quote while the error message contain a curly one.
So, when the script try to split the error message, only the second delimiter " into type " apply and item 2 of the resulting list is "string."

As I have no time to test with 10.10 and 10.11, I use an alternate scheme to treat the problem.
The script try to get the localized version of the new key.
If the localized string is different from the key, we are on a "modern" system and all is OK
If the localized string is equal to the key, we are on an "old" system and we make a new attempt extracting the localized version of the old key.
I tested it, it works.
You will find the edited script in message #9

Yvan KOENIG running Sierra 10.12.6 in French (VALLAURIS, France) vendredi 4 aout 2017 10:48:19

Offline

 

#15 2017-08-04 05:10:01 am

Nigel Garvey
Moderator
From:: Warwickshire, England
Registered: 2002-11-20
Posts: 4383

Re: Automatically Create One line from multiple lines of input

Hi.

Here's another entry. It very simply and quickly returns exactly what the OP asked for (with the trailing spaces in the first six "Test" lines preserved), though I'm not sure it's what was actually wanted.  hmm

Applescript:

set myString to "
Test1
Test2
Test3
Test4
Test5
Test6
Test7
"


set astid to AppleScript's text item delimiters
set AppleScript's text item delimiters to "\", \""
set newString to "{\"" & (myString's paragraphs from word 1 to word -1) & "\"}"
set AppleScript's text item delimiters to astid

display dialog newString


NG

Offline

 

#16 2017-08-04 08:03:19 am

Shane Stanley
Member
From:: Australia
Registered: 2002-12-07
Posts: 5136

Re: Automatically Create One line from multiple lines of input

Nigel Garvey wrote:

Here's another entry. It very simply and quickly returns exactly what the OP asked for (with the trailing spaces in the first six "Test" lines preserved), though I'm not sure it's what was actually wanted.  hmm



Here's a variation on your code -- if you squint hard, you could almost call it a one-liner wink

Applescript:

use framework "Foundation"
use framework "OSAKit"
use scripting additions

set myString to "
Test1
Test2
Test3
Test4
Test5
Test6
Test7
"


tell (current application's OSAScript's alloc()'s initWithSource:("paragraphs from word 1 to word -1 of \"" & myString & "\"")) to set {theString, attString} to its executeAndReturnDisplayValue:(reference) |error|:(missing value)
display dialog attString's |string|() as text

Crazy...

Last edited by Shane Stanley (2017-08-04 08:03:39 am)


Shane Stanley <sstanley@myriad-com.com.au>
www.macosxautomation.com/applescript/apps/

Offline

 

#17 2017-08-04 08:59:48 am

Nigel Garvey
Moderator
From:: Warwickshire, England
Registered: 2002-11-20
Posts: 4383

Re: Automatically Create One line from multiple lines of input

Shane Stanley wrote:

Here's a variation on your code


cool

-- if you squint hard, you could almost call it a one-liner wink


smile

Applescript:

use framework "Foundation"
use framework "OSAKit"
use scripting additions

set myString to "
Test1
Test2
Test3
Test4
Test5
Test6
Test7
"


display dialog (((current application's OSAScript's alloc()'s initWithSource:("paragraphs from word 1 to word -1 of \"" & myString & "\""))'s executeAndReturnDisplayValue:(reference) |error|:(missing value))'s end's |string|() as text)


NG

Offline

 

#18 2017-08-04 07:22:31 pm

Shane Stanley
Member
From:: Australia
Registered: 2002-12-07
Posts: 5136

Re: Automatically Create One line from multiple lines of input

cool cool cool cool

Last edited by Shane Stanley (2017-08-04 07:22:49 pm)


Shane Stanley <sstanley@myriad-com.com.au>
www.macosxautomation.com/applescript/apps/

Offline

 

#19 2017-08-12 02:32:33 pm

Prescience
Member
From:: United Kingdom
Registered: 2017-02-03
Posts: 43

Re: Automatically Create One line from multiple lines of input

WOW - thanks everyone for an interesting thread. 

I logged back in to see if anyone had posted, as I didn't get any notifications, and now feel bad that so much has happened, and I was oblivious to it all.

I will run through some of the examples and report back findings.

Thanks again to you all.

Last edited by Prescience (2017-08-12 02:33:05 pm)


Wisdom is knowing the power of experience, understanding the knowledge learnt on your personal journey through time, and having the empathy to share with others.

Offline

 

#20 2017-08-12 03:39:09 pm

Prescience
Member
From:: United Kingdom
Registered: 2017-02-03
Posts: 43

Re: Automatically Create One line from multiple lines of input

The code from Nigel works really well. Thanks.

Now to spice things up!  Would it be possible to create an application using the code below, which when run, reads the strings of data to be organised from an Excel spreadsheet, instead of having to add them into the code and then run it?

This would save even more time, and provide for greater flexibility and accuracy.

Nigel Garvey wrote:
Shane Stanley wrote:

Here's a variation on your code


cool

-- if you squint hard, you could almost call it a one-liner wink


smile

Applescript:

use framework "Foundation"
use framework "OSAKit"
use scripting additions

set myString to "
Test1
Test2
Test3
Test4
Test5
Test6
Test7
"


display dialog (((current application's OSAScript's alloc()'s initWithSource:("paragraphs from word 1 to word -1 of \"" & myString & "\""))'s executeAndReturnDisplayValue:(reference) |error|:(missing value))'s end's |string|() as text)

Last edited by Prescience (2017-08-12 03:42:20 pm)


Wisdom is knowing the power of experience, understanding the knowledge learnt on your personal journey through time, and having the empathy to share with others.

Offline

 

#21 2017-08-14 06:32:32 am

Nigel Garvey
Moderator
From:: Warwickshire, England
Registered: 2002-11-20
Posts: 4383

Re: Automatically Create One line from multiple lines of input

Prescience wrote:

Would it be possible to create an application using the code below, which when run, reads the strings of data to be organised from an Excel spreadsheet, instead of having to add them into the code and then run it?


I'm afraid I can't help with Excel. But you could possibly help any potential helpers by clarifying what the output should be and what the input could be. Stefan's second script, mine, and Shane's all produce exactly the output you requested in your first post from the input given. In this, the trailing space is removed from "Test7 ", but not from the other lines. This is a bit strange and the other scripts are intelligent attempts to guess at what you may actually have meant. It would help to have some clarity on this point. Also, the 'word' solutions will lose any non-alphanumeric characters at the beginning of the first line or at the end of the last, so it would be useful to know if the lines could contain any punctuation or spaces which need to be kept.


NG

Offline

 

#22 2017-08-14 08:46:11 am

haolesurferdude
Member
Registered: 2010-02-19
Posts: 104

Re: Automatically Create One line from multiple lines of input

Select a single column of your data starting with the first row of data thru the last row of data in Excel.  Then, run the following AppleScript:

Applescript:


use framework "Foundation"
use framework "OSAKit"
use scripting additions

tell application "Microsoft Excel"
   activate
   set rowCount to count of rows of selection
   set myString to "" as text
   repeat with j from 1 to rowCount
       set myString to myString & (value of row j of selection) as text
       if j < rowCount then
           set myString to myString & return as text
       end if
   end repeat
end tell

activate
display dialog (((current application's OSAScript's alloc()'s initWithSource:("paragraphs from word 1 to word -1 of \"" & myString & "\""))'s executeAndReturnDisplayValue:(reference) |error|:(missing value))'s end's |string|() as text)

Last edited by haolesurferdude (2017-08-14 08:47:11 am)

Offline

 

#23 2017-08-14 10:01:35 am

DJ Bazzie Wazzie
Member
From:: the Netherlands
Registered: 2004-10-20
Posts: 2709
Website

Re: Automatically Create One line from multiple lines of input

Prescience wrote:

reads the strings of data to be organised from an Excel spreadsheet, instead of having to add them into the code and then run it?



For python there is openpyxl so you can read the spreadsheet file and return the wanted data back to AppleScript without use of spreadsheet software like Microsoft Excel or Numbers.

Offline

 

#24 2017-08-15 03:04:42 am

Prescience
Member
From:: United Kingdom
Registered: 2017-02-03
Posts: 43

Re: Automatically Create One line from multiple lines of input

UPDATE: PM 2017-08-15

This code does as intended, with one small problem when used in the real world with longs strings of text, and more than 45 lines!  The text that appears in the output box is so long I can't copy all of it!

Would it be possible to offer a 'copy to clipboard' button, or output the text in another manor that will make copying the final result full proof?


This works perfectly. Thank you.

haolesurferdude wrote:

Select a single column of your data starting with the first row of data thru the last row of data in Excel.  Then, run the following AppleScript:

Applescript:


use framework "Foundation"
use framework "OSAKit"
use scripting additions

tell application "Microsoft Excel"
   activate
   set rowCount to count of rows of selection
   set myString to "" as text
   repeat with j from 1 to rowCount
       set myString to myString & (value of row j of selection) as text
       if j < rowCount then
           set myString to myString & return as text
       end if
   end repeat
end tell

activate
display dialog (((current application's OSAScript's alloc()'s initWithSource:("paragraphs from word 1 to word -1 of \"" & myString & "\""))'s executeAndReturnDisplayValue:(reference) |error|:(missing value))'s end's |string|() as text)

Last edited by Prescience (2017-08-15 11:10:49 am)


Wisdom is knowing the power of experience, understanding the knowledge learnt on your personal journey through time, and having the empathy to share with others.

Offline

 

#25 2017-08-15 03:09:05 am

Prescience
Member
From:: United Kingdom
Registered: 2017-02-03
Posts: 43

Re: Automatically Create One line from multiple lines of input

Thanks for the tip.  I am using Microsoft Excel so the script haolesurferdude created works well for me, and saves so much more time. 

However, your suggestion is great for anyone not using, or having access to, or even wanting to use Microsoft Excel or Numbers.

Thanks everyone for your input and assistance. smile

DJ Bazzie Wazzie wrote:
Prescience wrote:

reads the strings of data to be organised from an Excel spreadsheet, instead of having to add them into the code and then run it?



For python there is openpyxl so you can read the spreadsheet file and return the wanted data back to AppleScript without use of spreadsheet software like Microsoft Excel or Numbers.


Wisdom is knowing the power of experience, understanding the knowledge learnt on your personal journey through time, and having the empathy to share with others.

Offline

 

Board footer

Powered by FluxBB

RSS (new topics) RSS (active topics)