Link to home
Start Free TrialLog in
Avatar of wildzero
wildzero

asked on

Order two sets of numbers

Just going to cross link this thread to this one (hope thats allowed)
https://www.experts-exchange.com/questions/21873250/Two-sets-of-numbers-need-to-be-able-to-order-them.html

where I asked the question, just want to post it here to as this has to do with my Delphi application.
(and I doubt that area will get much people visiting it and it's relavent)


Thanks guys :D
SOLUTION
Avatar of BlackTigerX
BlackTigerX

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of wildzero
wildzero

ASKER

When I do
var
theList:TStringList;
begin
  theList:=TStringList.Create();
  theList.Add('10=5');
  theList.Add('12=8');
  theList.Add('20=12');
  theList.Add('5=5');
  theList.Add('9=0');
  theList.Sort();
  listbox1.Items.assign(theList);


it doesn't sem to sort them all (when I see them in the listbox....)
I don't understand your algorithm. You want to sort after left part? right part? results from left part minus right part ?
ASKER CERTIFIED SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
havn't come up with an algorithm yet.
Baically
want to sort the left numbers so they rank highest to lowerst however have to take into consideration the right numbers
like
9-5
and
9-6

it would rank as
9-6
9-5
or

10-8
and 12-11

would rank
10-8
12-11
sorting by left:

function Compare(Item1, Item2: TListItem; Data: integer):
  integer; stdcall;
var
  n1, n2: integer;
  s1, s2: string;
begin
  s1 := Trim(Copy(Item1.Caption, 1, Pos('-',Item1.Caption) - 1));
  //s2 := Trim(Copy(Item1.Caption, Pos('-',Item1.Caption) + 1, Length(Item1.Caption)));
  n1 := StrToInt(s1);// - StrToInt(s2);

  s1 := Trim(Copy(Item2.Caption, 1, Pos('-',Item2.Caption) - 1));
  //s2 := Trim(Copy(Item2.Caption, Pos('-',Item2.Caption) + 1, Length(Item2.Caption)));
  n2 := StrToInt(s1);// - StrToInt(s2);

  if n1 > n2 then
    Result := -1
  else if n1 < n2 then
    Result := 1
  else
    Result := 0;
end;
Let me understand:

Sort left from highter to lower. If equal sort by right.
I want to say from lower to highter to left and from highter to lower to right. This I understand from samples.

This is the code for sorting:


function Compare(Item1, Item2: TListItem; Data: integer):
  integer; stdcall;
var
  n1, n2: integer;
  s1, s2: string;
begin
  s1 := Trim(Copy(Item1.Caption, 1, Pos('-',Item1.Caption) - 1));
  n1 := StrToInt(s1);

  s1 := Trim(Copy(Item2.Caption, 1, Pos('-',Item2.Caption) - 1));
  n2 := StrToInt(s1);

  if n1 < n2 then
    Result := -1
  else if n1 > n2 then
    Result := 1
  else begin
    s2 := Trim(Copy(Item1.Caption, Pos('-',Item1.Caption) + 1, Length(Item1.Caption)));
    n1 := StrToInt(s2);
    s2 := Trim(Copy(Item2.Caption, Pos('-',Item2.Caption) + 1, Length(Item2.Caption)));
    n2 := StrToInt(s2);
    if n1 > n2 then
      Result := -1
    else if n1 < n2 then
      Result := 1
    else
      Result := 0;
  end;


end;
Almost
It's a hard one to understand...

Think of it like this
x - y

x = number of rooms
y = number of kids

y can be greater then x (ie 5 - 15)

What am trying to do is sort the list so
the top item contains the highest number of rooms to the lowest number of kids
So I guess you could look at the x:y as ratios...

the other thing have to look at is
6 - 0
that will rank higher then
8 - 4

That help?
Test:

10 - 6
14 - 9
9 - 5
9 - 6
8 - 2

Result:

8 - 2
9 - 6
9 - 5
10 - 6
14 - 9

you can play with < and > to next code part to set your order way. if change the > to <, then must change next < to >.

 if n1 > n2 then
      Result := -1
    else if n1 < n2 then
      Result := 1
    else
      Result := 0;
  end;
Next code will return an order from highter to lower left part. If have two or more equal left numbers then will order for right part from lower to hghter.


function Compare(Item1, Item2: TListItem; Data: integer):
  integer; stdcall;
var
  n1, n2: integer;
  s1, s2: string;
begin
  s1 := Trim(Copy(Item1.Caption, 1, Pos('-',Item1.Caption) - 1));
  n1 := StrToInt(s1);

  s1 := Trim(Copy(Item2.Caption, 1, Pos('-',Item2.Caption) - 1));
  n2 := StrToInt(s1);

  if n1 > n2 then
    Result := -1
  else if n1 < n2 then
    Result := 1
  else begin
    s2 := Trim(Copy(Item1.Caption, Pos('-',Item1.Caption) + 1, Length(Item1.Caption)));
    n1 := StrToInt(s2);
    s2 := Trim(Copy(Item2.Caption, Pos('-',Item2.Caption) + 1, Length(Item2.Caption)));
    n2 := StrToInt(s2);
    if n1 < n2 then
      Result := -1
    else if n1 > n2 then
      Result := 1
    else
      Result := 0;
  end;

end;
The idea is that you get the value for the left part in s1 and right in s2. After that you can play how you wish with results. Can make any math op. with these. And the results can be compared with

 if n1 < n2 then
      Result := -1
    else if n1 > n2 then
      Result := 1
    else
      Result := 0;

I must go now for one hour. But I will return to see if you need more help.
In that latest code I get this returned after sort
14-9
10-6
8-2
6-6
6-9

when it should be

8-2
14-9
10-6
6-6
6-9

If you do this

x - y

  Itm.SubItems.Add( FormatFloat('',x -((y / x) * y)) );

and then sort that - it almost gets there...
Hmmm I think it's going to be better to  sort by difference and if the difference is the same as another it sorts that one by the count

ie
x - y
c = (x - y)
Order by C DESC
Then loop and find any duplicate c and if so order them

Might code that up
mmm I guess now it's just a list of ratios
like
5:4
2:6

and ordering those
and just have to put in excpetipns for
ones like
5:5
9:9

and
ones like
5:19
 etc
It's hard to me to understand what you need. Anyway s1, s2 get the two values (rooms and kids) for first compared item:

  s1 := Trim(Copy(Item1.Caption, 1, Pos('-',Item1.Caption) - 1));
  s2 := Trim(Copy(Item1.Caption, Pos('-',Item1.Caption) + 1, Length(Item1.Caption)));
  n1 := Here you can make any math

same work for second compared item:

  s1 := Trim(Copy(Item2.Caption, 1, Pos('-',Item2.Caption) - 1));
  s2 := Trim(Copy(Item2.Caption, Pos('-',Item2.Caption) + 1, Length(Item2.Caption)));
  n2 := Here you can make any math


and finally order :

    if n1 < n2 then
      Result := -1
    else if n1 > n2 then
      Result := 1
    else
      Result := 0;

or:

    if n1 > n2 then
      Result := -1
    else if n1 < n2 then
      Result := 1
    else
      Result := 0;
Problems?
This is what I have done


Function GetWeight(iOccur, iResp : integer) : string;
var
  vO, vR, vFinal : real;
  sResult : string;
Begin
  vO := iOccur;
  vR := iResp;
  vFinal := vO * (( vO - Vr) / (vO + vR));

  Str(vFinal:10:2, sResult);
  Result := sResult;
End;
//==============================================================================

So when the items are added to the listview this happens

  caption := 'Something';
  subitems.add('10');
  subitems.add(5);
  subitems.add(GetWeight(10, 5));

then order the list by that column.
Works good