Wednesday, October 16, 2019

#1 2019-09-21 01:30:40 am

KniazidisR
Member
Registered: 2019-03-03
Posts: 614

Building a List of Lists

I would never have thought that I could not combine 2 lists into 1 list of lists.

Applescript:


set listA to {12, "cool", 1.1}
set listB to {13, "bool", pi, "A"}
set listC to listA & listB
-- Result: {12, "cool", 1.1, 13, "bool", 3.14159265359, "A"}

How to create one list, which contains N lists? How to append next list in repeat loop? This is the main problem.
I need as result  listC this form: {{12, "cool", 1.1},{13, "bool", pi, "A"}}

Last edited by KniazidisR (2019-09-21 01:41:17 am)


macOS Mojave -- version 10.14.4
Safari -- version 12.1

Offline

 

#2 2019-09-21 01:48:52 am

KniazidisR
Member
Registered: 2019-03-03
Posts: 614

Re: Building a List of Lists

I found:

Applescript:

set listA to {12, "cool", 1.1}
set listB to {13, "bool", pi, "A"}
set listC to {listA} & {listB}

I needed this for rounding list of numbers with Shane Stanley's great handler.
(See below the repeat loop using):

Applescript:


use AppleScript version "2.3.1"
use scripting additions
use framework "Foundation"

set numberList to {11.2345, pi}

set allResults to {}
repeat with aNumber in numberList
   set roundingResult to my roundNumber({theNumber:(aNumber as list), roundingMethod:"school", nDecimalPlaces:1})
   set end of allResults to roundingResult
end repeat
return allResults

on roundNumber(inputArgument)
   tell (inputArgument & {roundingMethod:"school", nDecimalPlaces:0}) to set {theNumber, roundingMethod, nDecimalPlaces} to {its theNumber, its roundingMethod, its nDecimalPlaces}
   if roundingMethod = "school" then
       set roundingMethod to (current application's NSRoundPlain)
   else if roundingMethod = "up" then
       set roundingMethod to (current application's NSRoundUp)
   else if roundingMethod = "down" then
       set roundingMethod to (current application's NSRoundDown)
   else if roundingMethod = "nearest" then
       set roundingMethod to (current application's NSRoundBankers)
   end if
   -- make decimal number
   if theNumber's class = text then
       set theNSDecimalNumber to current application's NSDecimalNumber's decimalNumberWithString:theNumber
   else
       set theNSDecimalNumber to current application's NSDecimalNumber's numberWithDouble:theNumber
   end if
   -- round it
   set theHandler to current application's NSDecimalNumberHandler's decimalNumberHandlerWithRoundingMode:roundingMethod scale:nDecimalPlaces raiseOnExactness:false raiseOnOverflow:true raiseOnUnderflow:true raiseOnDivideByZero:true
   set theRoundedNumber to theNSDecimalNumber's decimalNumberByRoundingAccordingToBehavior:theHandler
   -- get AS number
   try
       set roundednumber to theRoundedNumber's doubleValue()
   on error
       set roundednumber to "too large"
   end try
   -- get formatted strings
   set theFormatter to current application's NSNumberFormatter's alloc()'s init()
   theFormatter's setNumberStyle:(current application's NSNumberFormatterDecimalStyle)
   theFormatter's setMinimumFractionDigits:nDecimalPlaces
   theFormatter's setMaximumFractionDigits:nDecimalPlaces
   theFormatter's setHasThousandSeparators:false
   set decimalForm to (theFormatter's stringFromNumber:theRoundedNumber) as text
   theFormatter's setNumberStyle:(current application's NSNumberFormatterScientificStyle)
   theFormatter's setFormat:"0.#E+0;0.#E-0"
   set exponentialForm to (theFormatter's stringFromNumber:roundednumber) as text
   return {roundednumber:roundednumber, decimalForm:decimalForm, exponentialForm:exponentialForm}
end roundNumber

Shane, thanks!

Last edited by KniazidisR (2019-09-21 04:49:56 am)


macOS Mojave -- version 10.14.4
Safari -- version 12.1

Offline

 

#3 2019-09-21 02:58:18 am

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

Re: Building a List of Lists

Why not this simple:

Applescript:

set listA to {12, "cool", 1.1}
set listB to {13, "bool", pi, "A"}
set listC to {}
set end of listC to listA
set end of listC to listB
listC

Yvan KOENIG running High Sierra 10.13.6 in French (VALLAURIS, France) samedi 21 septembre 2019  10:58:13

Offline

 

#4 2019-09-21 04:09:16 am

KniazidisR
Member
Registered: 2019-03-03
Posts: 614

Re: Building a List of Lists

Yvan Koenig wrote:

Why not this simple:

Applescript:

set listA to {12, "cool", 1.1}
set listB to {13, "bool", pi, "A"}
set listC to {}
set end of listC to listA
set end of listC to listB
listC

Yvan KOENIG running High Sierra 10.13.6 in French (VALLAURIS, France) samedi 21 septembre 2019  10:58:13


Here is why. Try this in code above to see, that your code gives wrong results in repeat loop:

Applescript:


set allResults to {}
repeat with aNumber in numberList
set roundingResult to my roundNumber({theNumber:(aNumber as list), roundingMethod:"school", nDecimalPlaces:1})
set end of allResults to roundingResult
end repeat

Last edited by KniazidisR (2019-09-21 04:15:38 am)


macOS Mojave -- version 10.14.4
Safari -- version 12.1

Offline

 

#5 2019-09-21 04:20:10 am

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

Re: Building a List of Lists

Generally, when building a list from individual items, its faster to set the end of the list to each item as you get it. This works even when the item itself happens to be a list or a record. With this technique, the list being built is (nominally) always the same list, just with more items added.

Concatenating items to a list creates a new, longer list, as does concatenating two lists together. This is why the two lists need to be in lists themselves if you want the result to be a list containing those two lists. (Or just present the second list in a list if you want the result to be the same as the first list with the second in it.) While generally less efficient for repeated actions, there may be times when this technique is to be preferred.

The items in KniazidisR's larger script are actually records, but the same techniques are required because of a related issue. When items are concatenated together, the item on the right of the ampersand is automatically (if both necessary and possible) coerced to the same class as the item on the left for the concatenation. If this isn't possible, the concatenation result is a list containing both items. When concatenating an item to a list, its coercion to list, in most cases, will be a list containing just that item. But coercing a record to list produces a list containing just the record's values. So if you want to preserve the record as an entity in itself, it has to be explicitly presented in a list.


NG

Online

 

#6 2019-09-21 04:27:57 am

KniazidisR
Member
Registered: 2019-03-03
Posts: 614

Re: Building a List of Lists

Nigel Garvey wrote:


This is why the two lists need to be in lists themselves if you want the result to be a list containing those two lists.


OK, I put them in list with your method, but this again results not to list of lists:

Applescript:


set allResults to {}
repeat with aNumber in numberList
   set roundingResult to my roundNumber({theNumber:(aNumber as list), roundingMethod:"school", nDecimalPlaces:1})
   set end of allResults to {roundingResult}
end repeat

It seems, the reason is other. The AppleScript need first operand type to determine to what result you want coerce. The & method is preferable here.

Last edited by KniazidisR (2019-09-21 04:32:15 am)


macOS Mojave -- version 10.14.4
Safari -- version 12.1

Offline

 

#7 2019-09-21 04:33:43 am

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

Re: Building a List of Lists

KniazidisR wrote:


OK, I put them in list with your method, but this again results not to list of lists:

Applescript:


set allResults to {}
repeat with aNumber in numberList
   set roundingResult to my roundNumber({theNumber:(aNumber as list), roundingMethod:"school", nDecimalPlaces:1})
   set end of allResults to {roundingResult}
end repeat


No. The result from this is the result of the last action performed in the repeat. You do have to add return allResults at the end to see what you've got. And as I said above, your 'roundingResult' values are records, not lists.


NG

Online

 

#8 2019-09-21 04:43:43 am

KniazidisR
Member
Registered: 2019-03-03
Posts: 614

Re: Building a List of Lists

Nigel Garvey wrote:

No. The result from this is the result of the last action performed in the repeat. You do have to add return allResults at the end to see what you've got. And as I said above, your 'roundingResult' values are records, not lists.


Thank you, I somehow forgot about it. Then I will correct my script above, since the set end of... to... method is more efficient. smile

No need { and } too, as they are list of records already. I added return allResults to on run handler so that I no longer confuse people for no reason.

Last edited by KniazidisR (2019-09-21 04:59:49 am)


macOS Mojave -- version 10.14.4
Safari -- version 12.1

Offline

 

#9 2019-09-21 06:02:51 am

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

Re: Building a List of Lists

KniazidisR wrote:
Yvan Koenig wrote:

Why not this simple:

Applescript:

set listA to {12, "cool", 1.1}
set listB to {13, "bool", pi, "A"}
set listC to {}
set end of listC to listA
set end of listC to listB
listC

Yvan KOENIG running High Sierra 10.13.6 in French (VALLAURIS, France) samedi 21 septembre 2019  10:58:13


Here is why. Try this in code above to see, that your code gives wrong results in repeat loop:

Applescript:


set allResults to {}
repeat with aNumber in numberList
set roundingResult to my roundNumber({theNumber:(aNumber as list), roundingMethod:"school", nDecimalPlaces:1})
set end of allResults to roundingResult
end repeat



I apologize but when I run your script, I get:

{{roundednumber:11.2, decimalForm:"11,2", exponentialForm:"1,1E+1"}, {roundednumber:3.1, decimalForm:"3,1", exponentialForm:"3,1E+0"}}

which is what it was supposed to build, a list whose first item is the record

{roundednumber:11.2, decimalForm:"11,2", exponentialForm:"1,1E+1"}

and second item is the record :

{roundednumber:3.1, decimalForm:"3,1", exponentialForm:"3,1E+0"}

My original proposal may be rewritten with a loop:

Applescript:

set listA to {12, "cool", 1.1}
set listB to {13, "bool", pi, "A"}

set twoLists to {listA, listB}
set listC to {}
(*
repeat with aList in twoLists
   set end of listC to (contents of aList)
end repeat
listC
*)

repeat with i from 1 to count twoLists
   set end of listC to (get item i of twoLists)
end repeat
listC

The result would be the same:

{{12, "cool", 1.1}, {13, "bool", 3.14159265359, "A"}}

Yvan KOENIG running High Sierra 10.13.6 in French (VALLAURIS, France) samedi 21 septembre 2019  13:54:07

Offline

 

#10 2019-09-21 07:32:31 am

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

Re: Building a List of Lists

Hi Yvan.

KniazidisR's script wasn't returning his 'allResults' list. This was sorted out in posts #7 & #8 above.


NG

Online

 

Board footer

Powered by FluxBB

RSS (new topics) RSS (active topics)