<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:taxo="http://purl.org/rss/1.0/modules/taxonomy/" version="2.0">
  <channel>
    <title>topic SAS Tip: Sorting an Array in Descending Order (extension) in SAS Tips from the Community</title>
    <link>https://communities.sas.com/t5/SAS-Tips-from-the-Community/SAS-Tip-Sorting-an-Array-in-Descending-Order-extension/m-p/957202#M207</link>
    <description>&lt;P&gt;The article&amp;nbsp;&lt;A href="https://communities.sas.com/t5/SAS-Tips-from-the-Community/SAS-Tip-Sorting-an-Array-in-Descending-Order/m-p/442561#M145" target="_blank" rel="noopener"&gt;SAS Tip: Sorting an Array in Descending Order - SAS Support Communities&lt;/A&gt;&amp;nbsp;shows how to use call sortn (or call sortc) to sort an array in descending order, even though the call routines only support ascending order.&amp;nbsp; The "trick" is to list variables in an array in reverse sequence.&amp;nbsp; The example simply says to use,&amp;nbsp;instead of "array x{*} v1-v5;":&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt; array rev[*] v5-v1;
call sortn(of rev[*]);&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;to generate descending order for variables V1 through V5.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;But what if you don't have such conveniently named variables?&amp;nbsp; Let's say you have variables A, B, C, .... ,Z. and you want vars G through S to have values in descending order.&amp;nbsp; There is no way to declare the needed array without naming each array element in reverse order prior to the call sortn.&amp;nbsp; You can't simply use the endpoint names in the array declaration to support a descending sort.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;But you can use the endpoint names to define the array and a corresponding ordered hash object, and then retrieve the descending values back into the variables from endpoint to endpoint.&amp;nbsp; You do declare an array, but you don't need to list (or even know the names) of the interior variables:&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;data have;
  input 
a b c d e f g h i j  k  l  m  n  o  p  q  r  s  t  u  v  w  x  y  z;
datalines;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
run;

data want (drop=_: ii);
  set have;
  array vals  {*} G -- S;

  put "Before: " (g--s) (=);
  if _n_=1 then do;
    _value=.;
    declare hash hh (ordered:'d',multidata:'Y');
      hh.definekey('_value');
      hh.definedata('_value');
      hh.definedone();
    declare hiter hi ('hh');
  end;

  do ii=1 to dim(vals);
    hh.add(key:vals{ii},data:vals{ii});  *See note*;
  end;

  do _rc=hi.last() by 0 until (hi.prev()^=0);
    ii=ii-1;
    vals{ii}=_value;
  end;
  hh.clear();
  put 'After:  ' (g--s) (=);
run;
&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;Admittedly more overhead than an array statement plus a call sortn statement, but you avoid the requirement of correctly sequencing the names of all the variables in the array.&amp;nbsp; The longer the array, the more benefit from this technique.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Note:&lt;/P&gt;
&lt;P&gt;For a couple of days, I had erroneously used the hh.replace() method, but it prevents proper tracking of duplicate key values (which is why I used the multidata:"Y" option).&amp;nbsp; That has now been changed to hh.add(), which honors the duplicates.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Thank you&amp;nbsp;&lt;A href="https://communities.sas.com/t5/user/viewprofilepage/user-id/32733" target="_self"&gt;@FreelanceReinh&lt;/A&gt;&lt;/P&gt;</description>
    <pubDate>Sun, 26 Jan 2025 02:26:10 GMT</pubDate>
    <dc:creator>mkeintz</dc:creator>
    <dc:date>2025-01-26T02:26:10Z</dc:date>
    <item>
      <title>SAS Tip: Sorting an Array in Descending Order (extension)</title>
      <link>https://communities.sas.com/t5/SAS-Tips-from-the-Community/SAS-Tip-Sorting-an-Array-in-Descending-Order-extension/m-p/957202#M207</link>
      <description>&lt;P&gt;The article&amp;nbsp;&lt;A href="https://communities.sas.com/t5/SAS-Tips-from-the-Community/SAS-Tip-Sorting-an-Array-in-Descending-Order/m-p/442561#M145" target="_blank" rel="noopener"&gt;SAS Tip: Sorting an Array in Descending Order - SAS Support Communities&lt;/A&gt;&amp;nbsp;shows how to use call sortn (or call sortc) to sort an array in descending order, even though the call routines only support ascending order.&amp;nbsp; The "trick" is to list variables in an array in reverse sequence.&amp;nbsp; The example simply says to use,&amp;nbsp;instead of "array x{*} v1-v5;":&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt; array rev[*] v5-v1;
call sortn(of rev[*]);&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;to generate descending order for variables V1 through V5.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;But what if you don't have such conveniently named variables?&amp;nbsp; Let's say you have variables A, B, C, .... ,Z. and you want vars G through S to have values in descending order.&amp;nbsp; There is no way to declare the needed array without naming each array element in reverse order prior to the call sortn.&amp;nbsp; You can't simply use the endpoint names in the array declaration to support a descending sort.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;But you can use the endpoint names to define the array and a corresponding ordered hash object, and then retrieve the descending values back into the variables from endpoint to endpoint.&amp;nbsp; You do declare an array, but you don't need to list (or even know the names) of the interior variables:&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;data have;
  input 
a b c d e f g h i j  k  l  m  n  o  p  q  r  s  t  u  v  w  x  y  z;
datalines;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
run;

data want (drop=_: ii);
  set have;
  array vals  {*} G -- S;

  put "Before: " (g--s) (=);
  if _n_=1 then do;
    _value=.;
    declare hash hh (ordered:'d',multidata:'Y');
      hh.definekey('_value');
      hh.definedata('_value');
      hh.definedone();
    declare hiter hi ('hh');
  end;

  do ii=1 to dim(vals);
    hh.add(key:vals{ii},data:vals{ii});  *See note*;
  end;

  do _rc=hi.last() by 0 until (hi.prev()^=0);
    ii=ii-1;
    vals{ii}=_value;
  end;
  hh.clear();
  put 'After:  ' (g--s) (=);
run;
&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;Admittedly more overhead than an array statement plus a call sortn statement, but you avoid the requirement of correctly sequencing the names of all the variables in the array.&amp;nbsp; The longer the array, the more benefit from this technique.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Note:&lt;/P&gt;
&lt;P&gt;For a couple of days, I had erroneously used the hh.replace() method, but it prevents proper tracking of duplicate key values (which is why I used the multidata:"Y" option).&amp;nbsp; That has now been changed to hh.add(), which honors the duplicates.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Thank you&amp;nbsp;&lt;A href="https://communities.sas.com/t5/user/viewprofilepage/user-id/32733" target="_self"&gt;@FreelanceReinh&lt;/A&gt;&lt;/P&gt;</description>
      <pubDate>Sun, 26 Jan 2025 02:26:10 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Tips-from-the-Community/SAS-Tip-Sorting-an-Array-in-Descending-Order-extension/m-p/957202#M207</guid>
      <dc:creator>mkeintz</dc:creator>
      <dc:date>2025-01-26T02:26:10Z</dc:date>
    </item>
  </channel>
</rss>

