Welcome to our new forum
All users of the legacy CODESYS Forums, please create a new account at account.codesys.com. But make sure to use the same E-Mail address as in the old Forum. Then your posts will be matched. Close

Sorting an array

Runtime
NBCC
2017-08-22
2020-03-03
  • NBCC

    NBCC - 2017-08-22

    Hi all,

    I was wondering how you can sort out an array. I have around 50 values stacked in it. They are all mixed and i want to know if i can get the highest values first and the lowest values should be in the bottom. I have no idea how it is done. I was thinking with a for-loop but still can't figure it out.
    Has anyone got experience with this?

    Many thanks

     
  • teichhei

    teichhei - 2017-08-23

    Hi,

    You are on the right track. You need to compare each index with the next and swap if the value is bigger.
    You need two loops stacked in each other running them both for each element. Have a play, if you can't get it going I post an example.

    Sent from my SM-G935F using Tapatalk

     
  • Comingback4u

    Comingback4u - 2017-08-23

    Here is a quick and dirty way of doing it. I'm using version 3.5.5.0 so I don't have access to a lot of the new array features so I still pass pointers.

    FUNCTION SORTARRAY : BOOL
    VAR_INPUT
       ptrSortArray            :      POINTER TO ARRAY[0..0] OF INT;
       nArraySize               :      UINT;
       xSortDescending            :      BOOL;
    END_VAR
    VAR
       nCurrentLocation         :      UINT;
       nInnerLocation            :      UINT;
       ptrSmallerValue            :      POINTER TO INT;
       ptrLargerValue            :      POINTER TO INT;
       sTempValue               :      INT;
    END_VAR
    FOR nCurrentLocation := 0 TO nArraySize DO
       IF xSortDescending THEN
          ptrLargerValue := ADR(ptrSortArray[nCurrentLocation]);
       ELSE
          ptrSmallerValue := ADR(ptrSortArray[nCurrentLocation]);
       END_IF
       FOR nInnerLocation := (nCurrentLocation + 1) TO nArraySize DO
          IF xSortDescending THEN
             IF ptrSortArray^[nInnerLocation] > ptrLargerValue^ THEN
                ptrLargerValue := ADR(ptrSortArray[nInnerLocation]);
             END_IF
          ELSE
             IF ptrSortArray^[nInnerLocation] < ptrSmallerValue^ THEN
                ptrSmallerValue := ADR(ptrSortArray[nInnerLocation]);
             END_IF
          END_IF
       END_FOR
       sTempValue := ptrSortArray^[nCurrentLocation];
       IF xSortDescending THEN
          ptrSortArray^[nCurrentLocation] := ptrLargerValue^;
          ptrLargerValue^ := sTempValue;
       ELSE
          ptrSortArray^[nCurrentLocation] := ptrSmallerValue^;
          ptrSmallerValue^ := sTempValue;
       END_IF
    END_FOR
    

    Then to call it:

    PROGRAM PLC_PRG
    VAR
    //Test sort array
       aSorted                  :   ARRAY[0..nArraySize] OF INT;
       xRunSort               :   BOOL;
       xDescending               :   BOOL;
    END_VAR
    VAR CONSTANT
       nArraySize               :   INT                  :=   9;
    END_VAR
    IF xRunSort THEN
       SORTARRAY(ptrSortArray:= ADR(aSorted), nArraySize:= nArraySize, xSortDescending:= xDescending);
       xRunSort := FALSE;
    END_IF
    

    This was quickly thrown together so no guarantees but hope it at least gets you started.

     
  • NBCC

    NBCC - 2017-08-31

    Thanks a lot
    I had some other work to do (that's why my reply is a little late) but i'll try it out

     
  • NBCC

    NBCC - 2017-09-06

    Ok so i worked something out. Works perfect for me. Just want to share this

    IF sort THEN
    sort := FALSE; (visualisation stuff)
    FOR x := 1 TO max DO
    FOR y := 1 TO max-1 DO
    IF value[y] < value[y+1] THEN
    temp[1] := Value[y+1];
    Value[y+1] := Value[y];
    Value[e] := temp[1];
    END_IF
    END_FOR
    END_FOR
    END_IF

     
  • Comingback4u

    Comingback4u - 2017-09-06

    Hey NBCC,
    Thanks for posting your attempt at trying to come up with your own solution.
    Are there errors in your logic that happened when you copied onto here as I see some questionable areas that wouldn't work.
    1. I think "Value[e] := temp[1];" should actually be "Value[x] := temp[1];"
    2. You are never comparing X to anything.
    3. Using max as a variable couldn't be done. Maybe you just renamed this?
    4. When using your code with values 9,6,2,8,1,7,5,5,4,3 the results after sorting are 3,3,3,3,3,3,3,3,3,6.

    Hopefully the errors just happened when you copied it.

     
  • NBCC

    NBCC - 2017-09-07

    Comingback4u hat geschrieben:
    Hey NBCC,
    Thanks for posting your attempt at trying to come up with your own solution.
    Are there errors in your logic that happened when you copied onto here as I see some questionable areas that wouldn't work.
    1. I think "Value[e] := temp[1];" should actually be "Value[x] := temp[1];"
    2. You are never comparing X to anything.
    3. Using max as a variable couldn't be done. Maybe you just renamed this?
    4. When using your code with values 9,6,2,8,1,7,5,5,4,3 the results after sorting are 3,3,3,3,3,3,3,3,3,6.
    Hopefully the errors just happened when you copied it.

    Ok looks like i made some mistakes. I changed the code a little bit to make it look easier but maybe i should have given a little explanation.

    1. The Value[e] := temp[1] should be Value[y] := temp[1]; this is a temporary value
    2. X will just run to the value max (point 3 will explain what max means). No need to compare it with anything
    3. I changed the name. With max i mean the last row of the array (the array i get is always a different size) So if you got 6 values then x will run to 6, etc.
    4. Maybe you got those values because of my bad explanation in my previous post.

    Hope this works for you. If not, please let me know

     
  • Anonymous - 2017-09-13

    Originally created by: scott_cunningham

    Please take care of your execution time - as your list grows, you will create a large execution time and potentially create a PLC execution fault. If you use this solution (bubble sort) with motion control systems, you can have issues. Either modify the code so it only loops XX number of times per PLC scan or move it to a low priority task.

     
  • StoeberAs

    StoeberAs - 2020-01-30

    VAR_INPUT
    pT:POINTER TO INT;
    size:UINT;
    END_VAR
    VAR
    i:INT;
    iActualSize :UINT;
    iTemp :INT;
    j: INT;
    pCompare:POINTER TO INT;
    END_VAR

    iActualSize:=Size/SIZEOF(pT^);
    FOR i:=1 TO iActualSize-1 DO
    FOR j:=1 TO iActualSize-1 DO
    pCompare:=pT+SIZEOF(pT^);
    IF pT^>pCompare^ THEN
    iTemp:=pCompare^;
    pCompare^:= pT^;
    pT^:=iTemp;
    END_IF
    pT:=pT+SIZEOF(pT^);
    END_FOR
    pT:=pT-(iActualSize-1)*2;
    END_FOR

     
  • dFx

    dFx - 2020-03-03

    If you are interested into optimizing the sort, then, this is how .net framework handle unidimensional array sorting :

    If the partition size is less than or equal to 16 elements, it uses an insertion sort algorithm.

    If the number of partitions exceeds 2 * LogN, where N is the range of the input array, it uses a Heapsort algorithm.

    Otherwise, it uses a Quicksort algorithm

    Source : https://docs.microsoft.com/en-us/dotnet/api/system.array.sort?view=netframework-4.8#System_Array_Sort_System_Array_

     

Log in to post a comment.