2

I have a multidimensional array similar to the one described below:

Matrix => array(
 [0] => array( [0] => 7, [1] => 'hello' ),
 [1] => array( [0] => 3, [1] => 'there' ),
 [2] => array( [0] => 1, [1] => 'world' ),
)

What I'm trying to achieve is to sort this array using the values of Matrix[i][0]. What would be the most efficient way to do this? I looked into the recursive QuickSort function possibility, but it's rather complicated as I'm multidimensional arrays. There are many examples of quicksort, but none of them handle taking an "Array of Array of String" as an input.

Please ask for clarification if my text seems gibberish. I'm still fairly new to Delphi.

3
  • 5
    You don't have an array of array of string. What you say you have is something that Delphi cannot represent. You can't have heterogeneous arrays (arrays with values of more than one type, like integer and string). What you should have is an array of records, where the record's first field is an integer and the second is a string. Thinking about it as an array of records, does it make it any easier to understand that any sorting function should be able to work equally well with this data? The top-level array's data type (integer, string, record, array, whatever) doesn't matter. Commented Jan 30, 2013 at 0:03
  • 3
    Can you post the real code for your array declaration? Commented Jan 30, 2013 at 2:50
  • What have you tried, where did you get stuck? QuickSort is a fairly simple algorithm, especially if you find a ready-made implementation to alter for your own needs. QuickSort doesn't really care about what's in your array, all it needs is a way to compare two elements and a way to move them in the array. Ignore the fact that your array is multidimensional: you're sorting a simple unidimensional array where the elements of the array happen to also be unidimensional arrays. Commented Jan 30, 2013 at 10:16

2 Answers 2

4

As Rob pointed out in his comment, there's no way to have an multi-dimensional array that stores both integers and strings (without resorting to variants).

If it's really just an array containing integer/string pairs, it would be much easier to store them in a TStringList using the Strings and Objects properties, and then use CustomSort to sort on the Object values:

program Project2;

{$APPTYPE CONSOLE}

uses
  SysUtils, Classes;

function MySortProc(List: TStringList; Index1, Index2: Integer): Integer;
begin
  Result := Integer(List.Objects[Index1]) - Integer(List.Objects[Index2]);
end;

var
  SL: TStringList;
  i: Integer;
begin
  SL := TStringList.Create;
  try
    for i := 0 to 10 do
      SL.AddObject(Format('Item %d', [i]),  TObject(Random(i)));
    SL.CustomSort(@MySortProc);
    for i := 0 to SL.Count - 1 do
      WriteLn(Format('%d: %s', [Integer(SL.Objects[i]), SL[i]]));
    ReadLn;
  finally
    SL.Free;
  end;
end.

This produces

enter image description here

Sign up to request clarification or add additional context in comments.

1 Comment

Thank you a lot, Ken. Your example was really useful and solved my problem. It turns out I did have the wrong type to hold my data.
1

First of all I question whether or not you have chosen the correct type to represent your data structure. You say your type is

array of array of string

But it looks like the inner array always has exactly two elements, the first an integer, and the second a string. In that case the inner array should be replaced with a record.

type
  TMyElement = record
    ID: Integer;
    Name: string;
  end;

  TMyArray = array of TMyElement;

And now you just have a one dimensional array. I assume you have no difficulty sorting one of those.


But suppose that you really did need a multi-dimensional array. Suppose that the array was ragged, i.e. that different inner arrays had different lengths. You can still view that array as a one-dimensional array. Declare it like this:

  TStringArray = array of string;
  TMyArray = array of TStringArray;

Now you can sort TMyArray just as if it were a one-dimensional array.

Note that I needed to declare a type for the inner array. The reason being that the sort function needs to be able to compare and exchange elements of the outer array. So you'll need functions to do that. And you need to define a type to achieve that. For example, your exchange function might look like this:

procedure Exchange(Index1, Index2: Integer);
var
  temp: TStringArray;
begin
  temp := MyArray[Index1];
  MyArray[Index1] := MyArray[Index2];
  MyArray[Index2] := temp;
end;

Without defining TStringArray, this would not be possible. That's because of the rather stringent assignment compatibility rules for dynamic arrays.


You can extend to as many dimensions as you like:

  TString2DArray = array of TStringArray;
  TMyArray = array of TString2DArray;

Again, you can use your standard array sort to sort this three dimensional version of TMyArray.

1 Comment

Thank you, David, for clarifying this. I am fairly new to this language and did not expect so much hassle as in other languages much of this is a lot simpler. As I managed to solve my problem and complete the urgent application, I will now educate myself further.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.