Question

I have a TStringList that have quite many lines of strings.

What I want to do now is to sort this TStringList on certain values depending on which column in the TStringList they are at.

For instance.

adsfoiadjfoaidjfoaidfjo BABABA asdfsd 0101010
skfjlgjljkglsdkgjasaasd BABABA dafdff 0419299
asdaksdjakbkj3409560295 BABABA kjfhan 0923858
dsdddsdasdadasdasdasdgg BABABA dafdff 0419299
45645654654654654654666 BABABA dafdff 0489421
dsdddsdasdadasdasdasdgg CACACA dafdff 0419299

As you can see row two and four have the same value BABABA and also the same number in the end of the line, row five have the same BABABA but not the same number. Row six has the same number but not the same BABABA.

The correct way I want to sort them is

adsfoiadjfoaidjfoaidfjo BABABA asdfsd 0101010
skfjlgjljkglsdkgjasaasd BABABA dafdff 0419299
dsdddsdasdadasdasdasdgg BABABA dafdff 0419299
45645654654654654654666 BABABA dafdff 0489421
asdaksdjakbkj3409560295 BABABA kjfhan 0923858
dsdddsdasdadasdasdasdgg CACACA dafdff 0419299

What I want is to foremost sort after BABABA(column 25-30), and the if there is a match on the numbers, the numbers as well. If the numbers doesn't match it should sort after the BABABA if that doesn't sort it can be sorted in any way.

Was it helpful?

Solution

So you first want to sort on the second column, and then on the fourth column. Then you need TStringList.CustomSort.

From the help about the TStringListSortCompare function type:

Index1 and Index2 are indexes of the items in List to compare. The callback returns:

  • a value less than 0 if the string identified by Index1 comes before the string identified by Index2
  • 0 if the two strings are equivalent
  • a value greater than 0 if the string with Index1 comes after the string identified by Index2.

So if you first compare on the second column, and when equal, proceed comparing on the fourth. Assuming all text is capitalized, all strings are equal in size and with identical syntax, then this should work:

function CompareItems(List: TStringList; Index1, Index2: Integer): Integer;
begin
  Result := CompareStr(Copy(List[Index1], 25, 6), Copy(List[Index2], 25, 6));
  if Result = 0 then
    Result := CompareStr(Copy(List[Index1], 39, 7), Copy(List[Index2], 39, 7));
end;

Usage:

List.CustomSort(CompareItems);

OTHER TIPS

Define your own compare function that picks out that part of your strings that you wish to use for ordering:

function MyCompare(List: TStringList; Index1, Index2: Integer): Integer;

  function GetOrderingSubString(const s: string): string;
  begin
    Assert(Length(s)=45);
    Result := Copy(s, 25, 6) + Copy(s, 39, 7);
  end;

var
  s1, s2: string;

begin
  s1 := GetOrderingSubString(List[Index1]);
  s2 := GetOrderingSubString(List[Index2]);
  Result := CompareText(s1, s2); // or CompareStr, you decide
end;

And pass that function to CustomSort:

List.CustomSort(MyCompare);
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top