Solved

Quick Sort Custom Tag

Posted on 2001-06-21
20
471 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
  • 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
 

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
Enabling OSINT in Activity Based Intelligence

Activity based intelligence (ABI) requires access to all available sources of data. Recorded Future allows analysts to observe structured data on the open, deep, and dark web.

 
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

How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

Join & Write a Comment

Suggested Solutions

Preface This is the third article about the EE Collaborative Login Project. A Better Website Login System (http://www.experts-exchange.com/A_2902.html) introduces the Login System and shows how to implement a login page. The EE Collaborative Logi…
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 update a WordPress Site’s version. WordPress releases new versions of its software frequently and it is important to update frequently in order to keep your site secure, and to get new WordPress…
The viewer will learn how to count occurrences of each item in an array.

760 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

Need Help in Real-Time?

Connect with top rated Experts

20 Experts available now in Live!

Get 1:1 Help Now