Ada Sorting Composite Array - PullRequest
       9

Ada Sorting Composite Array

0 голосов
/ 25 февраля 2019

Я довольно новичок в Аде, и у меня есть вопрос.Этот Demo_Array_Sort из Rosetta Code использует функцию "<", чтобы определить, как сортировать массив.Сортирует по названию в алфавитном порядке.Я понимаю эту часть.Мой вопрос возникает так: </p>

Если в массиве Data есть несколько записей с одинаковым именем, и я хочу отсортировать список по значению в пределах Name, как бы ясделай это?Я попытался возиться с переопределением функции "<", но безрезультатно.Пожалуйста, помогите! </p>

with Ada.Strings.Unbounded; use Ada.Strings.Unbounded;
with Ada.Text_IO;           use Ada.Text_IO;
with Ada.Containers.Generic_Array_Sort;

procedure Demo_Array_Sort is

function "+" (S : String) return Unbounded_String renames To_Unbounded_String;

type A_Composite is
 record
         Name  : Unbounded_String;
         Value : Unbounded_String;
 end record;

function "<" (L, R : A_Composite) return Boolean is
 begin
 return L.Name < R.Name;
 end "<";

procedure Put_Line (C : A_Composite) is
 begin
      Put_Line (To_String (C.Name) & " " & To_String (C.Value));
 end Put_Line;

type An_Array is array (Natural range <>) of A_Composite;

procedure Sort is new Ada.Containers.Generic_Array_Sort (Natural, A_Composite, An_Array);

  Data : An_Array := (1 => (Name => +"Joe",    Value => +"5531"),
 2 => (Name => +"Adam",   Value => +"2341"),
 3 => (Name => +"Bernie", Value => +"122"),
 4 => (Name => +"Walter", Value => +"1234"),
 5 => (Name => +"David",  Value => +"19"));

begin
   Sort (Data);
 for I in Data'Range loop
      Put_Line (Data (I));
 end loop;
end Demo_Array_Sort; 

Пример данных:

 Data : An_Array := (1 => (Name => +"Joe",    Value => +"5531"),
 2 => (Name => +"Adam",   Value => +"2341"),
 3 => (Name => +"Bernie", Value => +"122"),
 4 => (Name => +"Walter", Value => +"1234"),
 5 => (Name => +"David",  Value => +"19")
 6 => (Name => +"David", Value => +"42")
 7 => (Name => +"David", Value => +"5"));

Будет выводить:

Adam 2341   
Bernie 122   
David 5
David 19
David 42   
Joe 5531   
Walter 1234 

Ответы [ 2 ]

0 голосов
/ 26 февраля 2019

Ниже приведен пример использования контейнера Vector.

with Ada.Text_IO; use Ada.Text_IO;
with Ada.Containers.Vectors;

procedure Main is
   type Surname is (Smith, Jones, Chen, Chavez);
   type Name is (John, Francis, Leslie, Margaret, George, Walter);

   type Person is record
      First : Name;
      Last  : Surname;
   end record;

   function Less(P1: Person; P2 : Person) return boolean is
   begin
      if P1.Last < P2.Last then
         return true;
      elsif
        P1.Last = P2.Last then
         return P1.First < P2.First;
      else
         return false;
      end if;
   end Less;


   procedure Print(P : Person) is
   begin
      Put_Line(P.Last'Image & ", " & P.First'Image);
   end Print;

   package Person_Vector is new Ada.Containers.Vectors(Index_Type   => Natural,
                                                       Element_Type => Person);
   use Person_Vector;
   package Person_Sort is new Generic_Sorting(Less);
   use Person_Sort;

   V : Vector;
   Temp : Person;
begin

   for N in Name loop
      for S in Surname loop
         Temp.First := N;
         Temp.Last := S;
         V.Append(Temp);
      end loop;
   end loop;

   Put_Line("Unsorted list:");
   for P of V loop
      Print(P);
   end loop;
   New_Line;

   Sort(V);

   Put_Line("Sorted list:");

   for P of V loop
      Print(P);
   end loop;

end Main;

Вывод этой программы:

Unsorted list:
SMITH, JOHN
JONES, JOHN
CHEN, JOHN
CHAVEZ, JOHN
SMITH, FRANCIS
JONES, FRANCIS
CHEN, FRANCIS
CHAVEZ, FRANCIS
SMITH, LESLIE
JONES, LESLIE
CHEN, LESLIE
CHAVEZ, LESLIE
SMITH, MARGARET
JONES, MARGARET
CHEN, MARGARET
CHAVEZ, MARGARET
SMITH, GEORGE
JONES, GEORGE
CHEN, GEORGE
CHAVEZ, GEORGE
SMITH, WALTER
JONES, WALTER
CHEN, WALTER
CHAVEZ, WALTER

Sorted list:
SMITH, JOHN
SMITH, FRANCIS
SMITH, LESLIE
SMITH, MARGARET
SMITH, GEORGE
SMITH, WALTER
JONES, JOHN
JONES, FRANCIS
JONES, LESLIE
JONES, MARGARET
JONES, GEORGE
JONES, WALTER
CHEN, JOHN
CHEN, FRANCIS
CHEN, LESLIE
CHEN, MARGARET
CHEN, GEORGE
CHEN, WALTER
CHAVEZ, JOHN
CHAVEZ, FRANCIS
CHAVEZ, LESLIE
CHAVEZ, MARGARET
CHAVEZ, GEORGE
CHAVEZ, WALTER

Обратите внимание, что поля отсортированы в порядке, указанном их перечисленияв программе.

0 голосов
/ 25 февраля 2019

В общих чертах,

  1. Измените Value компонент A_Composite на скалярный подтип, для которого "<" уже подходящим образом определен ;Я выбрал Natural:

    type A_Composite is
       record
          Name  : Unbounded_String;
          Value : Natural;
       end record;
    
  2. Теперь легко написать "<", который обрабатывает L.Name = R.Name:

    function "<" (L, R : A_Composite) return Boolean is
    begin
       if L.Name < R.Name then return True;
       elsif L.Name = R.Name then return L.Value < R.Value;
       else return False;
       end if;
    end "<";
    
  3. Обновление Put_Line соответственно:

    Put_Line (To_String (C.Name) & Natural'Image(C.Value));
    

Данные:

Data : An_Array := (
   1 => (Name => +"Joe",    Value => 5531 ),
   2 => (Name => +"Adam",   Value => 2341),
   3 => (Name => +"Bernie", Value => 122),
   4 => (Name => +"Walter", Value => 1234),
   5 => (Name => +"David",  Value => 19),
   6 => (Name => +"David",  Value => 42),
   7 => (Name => +"David",  Value => 5));

Консоль:

Adam 2341
Bernie 122
David 5
David 19
David 42
Joe 5531
Walter 1234
...