Solved

Quick Sort Custom Tag

Posted on 2001-06-21
20
478 Views
Last Modified: 2013-12-20
Could somebody please tell me where I can get a coldfusion custom tag for quick sort. I went to the Allaire site and downloaded the Merge Sort tag, which works fine, but it takes a very long time. I need a faster solution. Thanks in advance.

Nigel
0
Comment
Question by:theoneandonly
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 14
  • 6
20 Comments
 
LVL 4

Expert Comment

by:CF_Spike
ID: 6215754
Exactly what type of quick sort do you want?

Sorting structures, arrays or queries?

Spike
0
 

Author Comment

by:theoneandonly
ID: 6217547
0
 

Author Comment

by:theoneandonly
ID: 6217552
0
Secure Your WordPress Site: 5 Essential Approaches

WordPress is the web's most popular CMS, but its dominance also makes it a target for attackers. Our eBook will show you how to:

Prevent costly exploits of core and plugin vulnerabilities
Repel automated attacks
Lock down your dashboard, secure your code, and protect your users

 

Author Comment

by:theoneandonly
ID: 6217555
0
 

Author Comment

by:theoneandonly
ID: 6217558
0
 

Author Comment

by:theoneandonly
ID: 6217565
0
 

Author Comment

by:theoneandonly
ID: 6218843
I have written some code, it works but I am not sure how to return the sorted result. It returns only the first pass value.


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

<!---
  Custom Tag:             QuickSort
  Author:                   Nigel Pereira
  Creation_date:      15 June 2001
  Lastmod_date:            15 June 2001
 
  Attributes:            array                        (required) the 2 dimentional array to sort.
                              first                        (required) the first element of the array
                              last                        (required) the last element of the array
                              sortorder                  (optional) order to sort by
                                                            (default = "ASC") (asc,dsc)
                    sorttype                  (required) type of sort order
                                                            (default = "string") (date,string,integer)
                              arraywidth                  (required) the width of the array
                              sortcolumn                  (required) the column to sort by
                              

  Tag Usage:            <CF_QuickSort
                                    array="#arrSortedKey#"
                                    first="1"
                                    last="#ListLen(lStructKeys)#"
                                    sortorder="ASC"
                                    sorttype="date"
                                    arraywidth="#ListLen(lKeys)#"
                                    sortcolumn="#nKeyPos#"
                                    r_sortedArray="arrSorted">
                                    
  Description:            This tag will perform a quick sort on the array passed by the specified column in
                                either ascending or descending order.
--->  
<cfset array = ATTRIBUTES.array>
<cfset First = ATTRIBUTES.first>
<cfset Last = ATTRIBUTES.last>      
<Cfset SortType = "#ATTRIBUTES.SortType#">
<cfset sortcolumn = ATTRIBUTES.sortcolumn>
<cfset ArrayWidth = ATTRIBUTES.ArrayWidth>
<cfset thesortorder = "#ATTRIBUTES.sortorder#">
<cfparam name="Attributes.r_sortedArray" default="">

<!--- Set the structure of the return value --->
<cfif not IsDefined("Caller.#Attributes.r_sortedArray#")>
  <cfset temp= SetVariable("Caller.#Attributes.r_sortedArray#",ArrayNew(2))>
</cfif>

<cfif not IsArray(Evaluate("Caller.#Attributes.r_sortedArray#"))>
  <cfset temp= SetVariable("Caller.#Attributes.r_sortedArray#",ArrayNew(2))>
</cfif>
      
<cfscript>
      lo = first;
      hi = last;
      WriteOutput("Low=#lo# High=#hi#<br>");
</cfscript>
<cfif lo LT hi>
      <cfscript>
            midIndex = Int((lo + hi) / 2);
            mid = array[midIndex][sortcolumn];
            WriteOutput("Mid=#mid#<br>");
            for(k=1;lo LT hi;k=k+1)
            {
                  for(m=1;m LTE ArrayLen(array);m=m+1)
                  {
                        WriteOutput(ArrayToList(array[m]));
                        WriteOutput("      ");
                  }
                  WriteOutput("<br>");
                 for (;lo LT hi AND array[lo][sortcolumn] LT mid;)
                  {
                        lo=lo+1;
                }
                for (;lo LT hi AND array[hi][sortcolumn] GT mid;)
                  {
                        WriteOutput("#array[hi][1]# ");
                        WriteOutput("#array[hi][sortcolumn]#<br>");
                        hi=hi-1;
                }
                if (lo LT hi)
                  {
                        val=ArraySwap(array,lo,hi);
                        //for(i=1;i LTE ArrayWidth;i=i+1)
                        //{
                        //      T = array[lo][i];
                        //      array[lo][i] = array[hi][i];
                        //      array[hi][i] = T;
                        //}
                }
            }
            if (hi LT lo)
            {
                T = hi;
                hi = lo;
                lo = T;
            }
      </cfscript>
      <cf_QuickSort       array="#array#"
                              first="#Attributes.first#"
                              last="#lo#"
                              sortorder="#Attributes.sortorder#"
                              sorttype="#Attributes.sorttype#"
                              arraywidth="#Attributes.arraywidth#"
                              sortcolumn="#Attributes.sortColumn#"
                              r_sortedArray="#Attributes.r_sortedArray#">
      <cfif lo EQ first>
            <cfset lo2=lo+1>
            <cf_QuickSort       array="#array#"
                        first="#lo2#"
                        last="#last#"
                        sortorder="#Attributes.sortorder#"
                        sorttype="#Attributes.sorttype#"
                        arraywidth="#Attributes.arraywidth#"
                        sortcolumn="#Attributes.sortColumn#"
                        r_sortedArray="#Attributes.r_sortedArray#">
      <cfelse>
            <cf_QuickSort       array="#array#"
                        first="#lo#"
                        last="#last#"
                        sortorder="#Attributes.sortorder#"
                        sorttype="#Attributes.sorttype#"
                        arraywidth="#Attributes.arraywidth#"
                        sortcolumn="#Attributes.sortColumn#"
                        r_sortedArray="#Attributes.r_sortedArray#">
      </cfif>
      <cfset temp= SetVariable("Caller.#Attributes.r_sortedArray#",array)>
<cfelse>
      <cfset temp= SetVariable("Caller.#Attributes.r_sortedArray#",array)>
</cfif>
0
 

Author Comment

by:theoneandonly
ID: 6227110
Sorry Spike, I wasnt able to respond to your question, The sort I have written is for a 2 dimentional array, containing say employee information:
Employee No, Name, Age, Sex, Date of Birth, Department

Each row in the array contains these fields, I may want to sort based on Employee No, Name, Age, Date of Birth etc.

The code I wrote is correct, in the sense that it sorts the array, but I am not able to return the result, I get the resul from the first pass of the recursion.

Thanks again.

Nigel
0
 
LVL 4

Expert Comment

by:CF_Spike
ID: 6227197
ok,

I'll have a look at it. I've often wanted to write a utility to do something like that.

Spike
0
 

Author Comment

by:theoneandonly
ID: 6227365
Cheers Spike.
0
 
LVL 4

Expert Comment

by:CF_Spike
ID: 6227881
Is this what you wanted?

Calling Page:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">

<html>
<head>
     <title>Quick Sort</title>
</head>

<body>
<!--- 2 Dimensional array sorting. Second Array dimension represents:
1 - Employee No
2 - Name
3 - Age
4 - Sex
5 - Date of Birth
6 - Department --->

<CFSCRIPT>
  myArray = ArrayNew(2);
  myArray[1][1] = '1';
  myArray[1][2] = 'Spike';
  myArray[1][3] = '28';
  myArray[1][4] = 'Male';
  myArray[1][5] = 'CreateDate(1972,08,10)';
  myArray[1][6] = 'Training';
 
  myArray[2][1] = '2';
  myArray[2][2] = 'Jon';
  myArray[2][3] = '26';
  myArray[2][4] = 'Male';
  myArray[2][5] = 'CreateDate(1974,10,23)';
  myArray[2][6] = 'Consulting';
 
  myArray[3][1] = '2';
  myArray[3][2] = 'Bob';
  myArray[3][3] = '22';
  myArray[3][4] = 'Male';
  myArray[3][5] = 'CreateDate(1979,03,23)';
  myArray[3][6] = 'Sales';
 
  myArray[4][1] = '2';
  myArray[4][2] = 'Jane';
  myArray[4][3] = '20';
  myArray[4][4] = 'Female';
  myArray[4][5] = 'CreateDate(1980,11,29)';
  myArray[4][6] = 'Sales';
 
</CFSCRIPT>

<CF_QuickSort  
    Array="#MyArray#"
    r_Array="SortedArray"
    SortType="Numeric"
    SortItem="1">


</body>
</html>


custom Tag:

<CFPARAM NAME="Attributes.Array">
<CFPARAM NAME="Attributes.r_Array">

<!--- SortItem is the index in the second dimension
of the array which we want to sort by --->
<CFPARAM NAME="Attributes.SortItem">

<!--- SortType can be Numeric, Text, TextNoCase --->
<CFPARAM NAME="Attributes.SortType">

<!--- SortOrder can be Desc, Asc --->
<CFPARAM NAME="Attributes.SortOrder" DEFAULT="Asc">

<!--- Initialize a list to hold the array elements --->
<CFSET NameList = "">

<!--- Loop over the Array creating a list of the
elements by which we want to sort  --->
<CFLOOP From="1" To="#ArrayLen(Attributes.Array)#" index="i">

  <CFSET NameList = ListAppend(NameList,Attributes.Array[i][Attributes.SortItem])>

</CFLOOP>

<!--- Create a new sorted list. Sorting by the
parameters delcared above --->
<CFSET NewList = ListSort(NameList,Attributes.SortType,Attributes.SortOrder)>

<!--- Create a New array sorted according to our requirements --->
<CFSET NewArray = ArrayNew(2)>
<CFSET Counter = 1>
<CFLOOP LIST="#newList#" INDEX="i">
<CFSET NewArray[counter] = Attributes.Array[ListFind(NameList,i)]>
<CFSET Counter = Counter + 1>
</CFLOOP>

<CFSET "Caller.#Attributes.r_Array#" = NewArray>

Spike
0
 

Author Comment

by:theoneandonly
ID: 6227946
Give me a couple of minutes Spike, I'll just check it.
0
 

Author Comment

by:theoneandonly
ID: 6228095
Thats great thanks, I think I have to modify it for date sort and also it does not work for duplicate values on the sort index.

Nigel
0
 
LVL 4

Expert Comment

by:CF_Spike
ID: 6228131
That shouldn't be too hard.

Let me know if you have any problems.

Spike
0
 

Author Comment

by:theoneandonly
ID: 6228162
Thats great thanks, I think I have to modify it for date sort and also it does not work for duplicate values on the sort index.

Nigel
0
 

Author Comment

by:theoneandonly
ID: 6228243
Spike,

Sorry to bother you again, I cant seem to figure out how to do it, could you help me. I tried to remove the array element from the original array after setting it to the new array. But, I am getting an error.

Error Occurred While Processing Request
Error Diagnostic Information

An error occurred while evaluating the expression:


 NewArray[counter] = Attributes.Array[ListFind(NameList,i)]



Error near line 33, column 15.
--------------------------------------------------------------------------------

The [] operator can only be applied to an indexed object. The provided object "Attributes.Array" is not indexed in dimension 1. In ColdFusion indexed objects can be query columns, arrays and structs.


The error occurred while processing an element with a general identifier of (CFSET), occupying document position (33:1) to (33:66).


Date/Time: 06/26/01 17:19:00
Browser: Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 4.0)
Remote Address: 127.0.0.1

Thanks.

Nigel
0
 
LVL 4

Expert Comment

by:CF_Spike
ID: 6228260
Erm...

ok, but what were you trying to achieve when this happened?

Spike
0
 

Author Comment

by:theoneandonly
ID: 6228441
I sorted out the duplicate things, all I have to do is the date sort. Thanks
0
 
LVL 4

Accepted Solution

by:
CF_Spike earned 100 total points
ID: 6229299
ok,

This one works with dates, but you'll have to add the duplicate stuff yourself.

Calling page:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">

<html>
<head>
      <title>Quick Sort</title>
</head>

<body>
<!--- 2 Dimensional array sorting. Second Array dimension represents:
1 - Employee No
2 - Name
3 - Age
4 - Sex
5 - Date of Birth
6 - Department --->

<CFSCRIPT>
  myArray = ArrayNew(2);
  myArray[1][1] = '1';
  myArray[1][2] = 'Spike';
  myArray[1][3] = '28';
  myArray[1][4] = 'Male';
  myArray[1][5] = CreateDate(1972,08,10);
  myArray[1][6] = 'Training';
 
  myArray[2][1] = '2';
  myArray[2][2] = 'Jon';
  myArray[2][3] = '26';
  myArray[2][4] = 'Male';
  myArray[2][5] = CreateDate(1979,10,23);
  myArray[2][6] = 'Consulting';
 
  myArray[3][1] = '3';
  myArray[3][2] = 'Bob';
  myArray[3][3] = '22';
  myArray[3][4] = 'Male';
  myArray[3][5] = CreateDate(1974,03,23);
  myArray[3][6] = 'Sales';
 
  myArray[4][1] = '4';
  myArray[4][2] = 'Jane';
  myArray[4][3] = '20';
  myArray[4][4] = 'Female';
  myArray[4][5] = CreateDate(1980,11,29);
  myArray[4][6] = 'Sales';
 
  myArray[5][1] = '5';
  myArray[5][2] = 'Anne';
  myArray[5][3] = '30';
  myArray[5][4] = 'Female';
  myArray[5][5] = CreateDate(1971,11,29);
  myArray[5][6] = 'Sales';
 
</CFSCRIPT>


<CF_QuickSort  
    Array="#MyArray#"
    r_Array="SortedArray"
    SortType="Date"
    SortItem="5"
    SortOrder="Asc">

</body>
</html>

Custom Tag:

<CFPARAM NAME="Attributes.Array">
<CFPARAM NAME="Attributes.r_Array">

<!--- SortItem is the index in the second dimension
of the array which we want to sort by --->
<CFPARAM NAME="Attributes.SortItem">

<!--- SortType can be Numeric, Text, TextNoCase, date --->
<CFPARAM NAME="Attributes.SortType">

<!--- SortOrder can be Desc, Asc --->
<CFPARAM NAME="Attributes.SortOrder" DEFAULT="Asc">

<!--- Initialize a list to hold the array elements --->
<CFSET NameList = "">

<!--- Loop over the Array creating a list of the
elements by which we want to sort  --->
<CFLOOP From="1" To="#ArrayLen(Attributes.Array)#" index="i">
<CFSET ThisItem = Attributes.Array[i][Attributes.SortItem]>
<CFSET NameList = ListAppend(NameList,ThisItem)>

<!--- Handle the special case where the sort type is date --->
<CFIF NOT CompareNoCase(Attributes.SortType,'Date')>
<!--- Make sure that the sort field is a date field --->
<CFIF NOT IsDate(ThisItem)>
  <CFABORT SHOWERROR="A sort type of date was requested for the custom tag quicksort, but the field to be sorted is not a date field">
</CFIF>
<!--- Initialize the newlist --->
<CFPARAM NAME="NewList" DEFAULT="">
 
  <!--- Only perform the sort once we have an element in the list --->
  <CFIF i GT 1>
    <!--- Loop over the current elements in the sorted list --->
    <CFLOOP FROM="1" TO="#ListLen(NewList)#" INDEX="j">
      <!--- Check if we are doing a descending or ascending sort --->
      <CFIF CompareNoCase(Attributes.SortOrder,'Asc')>
        <!--- Descending sort type --->
     
        <!--- Check if the date is before the the current list element, but after the next --->
        <CFIF DateCompare(ListGetAt(NewList,j),ThisItem) GT 0 AND J LT ListLen(NewList) AND DateCompare(ListGetAt(NewList,J+1),ThisItem) LT 1>
          <CFSET NewList = ListInsertAt(NewList,J+1,ThisItem)>
          <CFBREAK>
        <!--- Check if the date is later than the current element --->
        <CFELSEIF DateCompare(ListGetAt(NewList,j),ThisItem) LT 1>
          <CFSET NewList = ListPrepend(NewList,ThisItem)>
          <CFBREAK>
        <!--- If we got to here the date must go at the end of the list --->
        <CFELSEIF J EQ ListLen(NewList)>
          <CFSET NewList = ListAppend(NewList,ThisItem)>
        </CFIF>
      <CFELSE>
      <!--- Ascending sort type --->
     
        <!--- Check if the date is after the current date, but before the next --->
        <CFIF DateCompare(ListGetAt(NewList,j),ThisItem) LT 1 AND J LT ListLen(NewList) AND DateCompare(ListGetAt(NewList,J+1),ThisItem) GT 0>
          <CFSET NewList = ListInsertAt(NewList,J+1,ThisItem)>
          <CFBREAK>
        <!--- Check if the date is before the current date --->
        <CFELSEIF DateCompare(ListGetAt(NewList,j),ThisItem) GT 0>
          <CFSET NewList = ListPrepend(NewList,ThisItem)>
          <CFBREAK>
        <!--- If we got to here the date must go at the end of the list --->
        <CFELSEIF J EQ ListLen(NewList)>
          <CFSET NewList = ListAppend(NewList,ThisItem)>
        </CFIF>
      </CFIF>
    </CFLOOP>
 
  <!--- First time through the outer loop we put the item in newlist --->
  <CFELSE>
    <CFSET NewList = ListAppend(NewList,ThisItem)>
  </CFIF>
 
</CFIF>

</CFLOOP>

<!--- Create a new sorted list if sort type isn't date. Sorting by the
parameters declared above  --->
<CFIF CompareNoCase(Attributes.SortType,'Date')>
  <CFSET NewList = ListSort(NameList,Attributes.SortType,Attributes.SortOrder)>
</CFIF>
<!--- Create a New array sorted according to our requirements --->
<CFSET NewArray = ArrayNew(2)>
<CFSET Counter = 1>
<CFLOOP LIST="#newList#" INDEX="i">
<CFSET NewArray[counter] = Attributes.Array[ListFind(NameList,i)]>
<CFSET Counter = Counter + 1>
</CFLOOP>

<CFSET "Caller.#Attributes.r_Array#" = NewArray>

Spike
0
 

Author Comment

by:theoneandonly
ID: 6230423
Thanks a lot Spike I sussed it out myself yesterday.

Nigel
0

Featured Post

Manage your data center from practically anywhere

The KN8164V features HD resolution of 1920 x 1200, FIPS 140-2 with level 1 security standards and virtual media transmissions at twice the speed. Built for reliability, the KN series provides local console and remote over IP access, ensuring 24/7 availability to all servers.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

If you don't have the right permissions set for your WordPress location in IIS, you won't be able to perform automatic updates. Here's how to fix the problem.
JavaScript has plenty of pieces of code people often just copy/paste from somewhere but never quite fully understand. Self-Executing functions are just one good example that I'll try to demystify here.
The purpose of this video is to demonstrate how to Import and export files in WordPress. This will be demonstrated using a Windows 8 PC. Go to your WordPress login page. This will look like the following: mywebsite.com/wp-login.php : Click on Too…
The viewer will learn how to create and use a small PHP class to apply a watermark to an image. This video shows the viewer the setup for the PHP watermark as well as important coding language. Continue to Part 2 to learn the core code used in creat…

734 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question