Tell me more ×
Stack Overflow is a question and answer site for professional and enthusiast programmers. It's 100% free, no registration required.

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.

share|improve this question
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. – Rob Kennedy Jan 30 at 0:03
3  
Can you post the real code for your array declaration? – jachguate Jan 30 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. – Cosmin Prund Jan 30 at 10:16

2 Answers

up vote 4 down vote accepted

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

share|improve this answer
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. – Lightheaded Jan 30 at 16:58

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.

share|improve this answer
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. – Lightheaded Jan 30 at 17:00

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.