Re: Sort Multidimensional Array by Column 5
Re: Sort Multidimensional Array by Column 5
- Subject: Re: Sort Multidimensional Array by Column 5
- From: KOENIG Yvan <email@hidden>
- Date: Tue, 5 Oct 2010 18:48:30 +0200
Le 5 oct. 2010 à 17:29, Richard Lake a écrit :
> Hello,
>
> I am returning to an old issue from this summer that never got resolved, it involves reading a .csv file into an array, sorting the array by a column and then writing the array back to disc. The input and output delimited must be retained always.
>
> I require a simple routine that can be called at will which will sort Column 5 in descending order. This column can also contain nothing but empty quotes.
>
> Sometime ago I was a given a solution that involved the use of unix commands Head, Tail, Tr and Sort. This refused to work no matter what I tried. For starters -n argument of Head wouldn't work I had to use -c bytenumber instead, but the list never got sorted anyway!
>
> Column Headings and example of how CSV file is stored.
>
> "Customer GUID","Form GUID","Contact GUID","Form Type","Ref No","Account Number","Company Name","Contact Name","Contact Address","Email address","Artwork awaiting Response","Days no Response","Special Pricing","Date"
> "17F1098A-482E-4BCB-BC17-B56094FF7CC1","ADB3CC97-0A42-40FF-9C63-10AB043A0F7E","66864065-0256-41E3-AFCF-CC7053DAD196","PF","","S0154C","Synectic Systems Group Ltd","A Name","","email@address","Yes","2","No",""
> "43C79C66-2127-41B9-B444-34EAB49DEB68","7AF809BA-10F9-4997-858D-DF3ACE829BC0","ED9FF7CF-ECF0-4D2D-BAB9-687B4AEEF109","QT","2940","M0012C","Manchester Metropolitan University[] The","A Name","An Address[]2nd Line[]3rd Line[]Etc[]","email@address","No","1","No",""
> "41A9C623-3E6E-44E1-81D6-FC5B57FCC7D8","4625DC32-B013-42CC-BFD4-73962A3106F4","1D54FDFE-731E-4B85-BD7B-416A7B05AA90","SO","3110","C0250C","Chem-dry (uk) Ltd","A Name","An Address[]2nd Line[]3rd Line[]Etc[]","email@address","Yes","2","No",""
>
> The array retains its data in this fashion and I have no plans to change this behaviour as its used countless times as part of a much wider application.
>
> set formData to {{"7C925871-2545-458E-9E1A-F3362F5010BE", "CFB29657-ABBA-4AAC-83CF-F436D1AFE3BE", "2ADC20E6-6AB3-4FD9-B137-BAD34D1B580D", "QT", "2942", "C0067C", "Conocophillips", "A Name", "An Address[]2nd Line[]3rd Line[]Etc[]", "email@address", "No", "1", "No", ""}, {"7C925871-2545-458E-9E1A-F3362F5010BE", "97A6977D-B0F4-480B-ACA5-9977E7307996", "2CAC23D0-AEF7-4194-AD1C-201B053298A0", "SO", "3111", "C0067C", "Conocophillips", "A Name", "An Address[]2nd Line[]3rd Line[]Etc[]", "aemail@address", "No", "1", "No", ""}, {"059B2178-D55B-4542-A794-0B4079F6B007", "C6484FD1-989C-4DA5-8AF8-161769BB1146", "5734F334-2851-496A-82D0-B6A7658ACA53", "SO", "3112", "B0063C", "Exova", "A Name", "An Address[]2nd Line[]3rd Line[]Etc[]", "email@address", "Yes", "1", "Yes", ""}}
>
> ----
>
> If anyone can offer a working solution I'd like to hear it.
>
Here is a proposal using a script grabbed from :
http://trad.applescript.free.fr/aplea.html
I just added a new comparison function :
on cmpdesc5(n1, n2) -- tri descendant des nombres et des chaînes
return (item 5 of n1) > (item 5 of n2)
end cmpdesc5
--[SCRIPT]
(* Tri par interclassement
--> renvoie une copie triée de la liste originale.
Implémentation: L. Sebilleau & D. Varlet
*)
on intersort(laListe, fcmp)
-- le deuxième paramètre est un pointeur sur la fonction de comparaison à employer
script lstock -- l'intérêt de ce script est d'accélérer le traitement des listes
property listeorg : laListe
property liste1 : {}
property liste2 : {}
property listea : {}
property listeb : {}
property lister : {}
property Compare : fcmp -- ce pointeur de fonction est stocké là
end script
-- répartition des éléments à trier en sous-listes de longueur deux
tell lstock
set ct to (its listeorg)'s length
set flag to false
if (ct mod 2) = 1 then
set ct to ct - 1
set flag to true
end if
repeat with i from 1 to ct by 2
set x to item i of its listeorg
set y to item (i + 1) of its listeorg
if Compare(x, y) then -- la fonction de comparaison est employée ici
{x, y}
else
{y, x}
end if
set the end of its liste1 to result
end repeat
if flag then set the end of its liste1 to {item -1 of its listeorg}
-- interclassement des listes contenues dans liste1
repeat
set ct to (its liste1)'s length
if ct = 1 then exit repeat -- tant qu'il me reste plusieurs listes, c'est pas fini
set flag to false
if (ct mod 2) = 1 then
set ct to ct - 1
set flag to true
end if
set its liste2 to {}
repeat with i from 1 to ct by 2 -- on prend les listes 2 par 2
set its listea to item i of its liste1
set its listeb to item (i + 1) of its liste1
set its lister to {} -- pour n'en faire qu'une seule dans celle-là
set cta to (its listea)'s length
set ctb to (its listeb)'s length
set ya to 1
set yb to 1
repeat
-- la fonction de comparaison est aussi employée ici:
if Compare(item yb of its listeb, item ya of its listea) then -- comparaison des premiers éléments
set the end of its lister to (item yb of its listeb) -- "extraction" du premier
set yb to yb + 1
if yb > ctb then -- si cette liste est maintenant vide, on arrête là.
if ya ≤ cta then -- il peut rester des éléments dans l'une des listes
set its lister to (its lister) & (items ya thru -1 of its listea)
end if
exit repeat
end if
else -- symétrique dans le cas inverse
set the end of its lister to (item ya of its listea)
set ya to ya + 1
if ya > cta then
if yb ≤ ctb then -- il peut rester des éléments dans l'une des listes
set its lister to (its lister) & (items yb thru -1 of its listeb)
end if
exit repeat
end if
end if
end repeat
-- la nouvelle liste produite par la fusion est ajoutée en tant que liste au résultat
set the end of its liste2 to its lister
end repeat -- et on recommence tant qu'il reste des paires de listes
-- sans oublier l'orpheline si le nombre de listes est impair: on l'ajoute simplement à la fin
if flag then set the end of its liste2 to {} & item -1 of its liste1
set its liste1 to its liste2 -- et c'est reparti pour un tour
end repeat
return first item of its liste1 -- parce que c'est une liste de listes, même si elle n'en contient plus qu'une seule
end tell
end intersort
----------- les fonctions de comparaison ------------
on cmpasc(n1, n2) -- pour le tri ascendant des nombres et des chaînes
return n1 < n2
end cmpasc
on cmpdesc(n1, n2) -- tri descendant des nombres et des chaînes
return n1 > n2
end cmpdesc
on recmp(n1, n2) -- tri par noms
return (nom of n1 < nom of n2)
end recmp
on agecmp(n1, n2) -- tri par âges
return (Age of n1 < Age of n2)
end agecmp
on cmpdesc5(n1, n2) -- tri descendant des nombres et des chaînes
return (item 5 of n1) > (item 5 of n2)
end cmpdesc5
---------------- Pour tester ----------------
set maListe to {{"7C925871-2545-458E-9E1A-F3362F5010BE", "CFB29657-ABBA-4AAC-83CF-F436D1AFE3BE", "2ADC20E6-6AB3-4FD9-B137-BAD34D1B580D", "QT", "2942", "C0067C", "Conocophillips", "A Name", "An Address[]2nd Line[]3rd Line[]Etc[]", "email@address", "No", "1", "No", ""}, {"7C925871-2545-458E-9E1A-F3362F5010BE", "97A6977D-B0F4-480B-ACA5-9977E7307996", "2CAC23D0-AEF7-4194-AD1C-201B053298A0", "SO", "3111", "C0067C", "Conocophillips", "A Name", "An Address[]2nd Line[]3rd Line[]Etc[]", "aemail@address", "No", "1", "No", ""}, {"059B2178-D55B-4542-A794-0B4079F6B007", "C6484FD1-989C-4DA5-8AF8-161769BB1146", "5734F334-2851-496A-82D0-B6A7658ACA53", "SO", "3112", "B0063C", "Exova", "A Name", "An Address[]2nd Line[]3rd Line[]Etc[]", "email@address", "Yes", "1", "Yes", ""}}
set maListe to intersort(maListe, my cmpdesc5)
--[/SCRIPT]
Yvan KOENIG (VALLAURIS, France) mardi 5 octobre 2010 18:48:23
_______________________________________________
Do not post admin requests to the list. They will be ignored.
AppleScript-Users mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
Archives: http://lists.apple.com/archives/applescript-users
This email sent to email@hidden