Есть ли способ найти индекс элемента массива указателей?

Есть ли способ найти индекс элемента массива указателей?

Код выглядит так:

type

  TArrayItem = record
   Field1: string;
   Field2: integer;
   Field3: boolean;
  end;

var 
  MyItem: TArrayItem; 
  MyArray: array[1..100] of TArrayItem;

Допустим, я беру элемент из массива (MyItem:=MyArray[20];). После этого я сортирую массив и расположение элементов меняется; Теперь, как я могу найти новый индекс MyItem?

2 ответа

Решение

У вас нет массива указателей. В отличие от class, который является ссылочным типом, record это тип значения Как вы объявили массив, данные элемента копируются всякий раз, когда вы делаете назначение. Итак, когда вы назначаете элемент массива MyItemВы делаете копию данных этого элемента, но не получаете указатель на исходный элемент.

В любом случае, если у вас есть массив элементов или массив указателей на элементы, ответ один и тот же: единственный способ найти элемент в массиве - это циклически просмотреть массив вручную, например:

var 
  MyItem: TArrayItem; 
  MyArray: array[1..100] of TArrayItem;
  I: Integer;

MyItem := MyArray[20];

// sort the array...

for I := Low(MyArray) to High(MyArray) do
begin
  if (MyArray[I].Field1 = MyItem.Field1) and
     (MyArray[I].Field2 = MyItem.Field2) and
     (MyArray[I].Field3 = MyItem.Field3) then
  begin
    // item was found at index I...
  end;
end;

В противном случае, динамически размещайте ваши элементы в куче и сохраняйте их указатели в TList или же TList<T>как они выставляют IndexOf() методы. И сортировка будет быстрее, поскольку вы перемещаете указатели, а не полные копии данных.

Не существует встроенной механики для выполнения того, что вы просите. Вам придется перебирать массив и идентифицировать соответствующий элемент, чтобы определить его положение в этом массиве.

В этом случае вы также должны заметить, что, хотя в вашем вопросе говорится, что у вас есть "массив указателей", код, который вы опубликовали, - это не массив указателей, а массив записей, которые являются типами значений, а не ссылками, поэтому этот код:

MyItem := MyArray[20];

Не получает ссылку на 20-й элемент в MyArray, а создает его копию. Код для идентификации элемента в массиве довольно заметно меняется, когда вы находите копию элемента по сравнению со ссылкой на элемент.

Чтобы найти элемент в массиве указателей:

var
   i, indexOfItem: Integer;
   item: ^TArrayItem;
   theArray: array[1..100] of ^TArrayItem;


item := theArray[20];

indexOfItem := -1;
for i := Low(theArray) to High(theArray) do
  if (theArray[i] = item) then
  begin
    indexOfItem := i;
    BREAK;
  end;

Чтобы найти элемент в массиве записей, вы должны проверить равенство полей записей отдельно, поскольку вы не можете сравнить две записи в целом:

var
   i, indexOfItem: Integer;
   item: TArrayItem;
   theArray: array[1..100] of TArrayItem;


item := theArray[20];

indexOfItem := -1;
for i := Low(theArray) to High(theArray) do
  if   (theArray[i].Field1 = item.Field1) 
   and (theArray[i].Field2 = item.Field2) 
   and (theArray[i].Field3 = item.Field3) then
  begin
    indexOfItem := i;
    BREAK;
  end;

Вы также должны знать, что в этом последнем случае есть встроенное предположение, что никакие два элемента не будут иметь одинаковые значения для полей записи, поскольку будет идентифицирован только первый соответствующий элемент.

NB. Приведенный выше код не предназначен для того, чтобы быть надежными решениями, а только для демонстрации соответствующих принципов.

Еще одна вещь, о которой следует помнить, это вероятность того, что у вас есть массив записей, но вы получили указатель на какой-то элемент в этом массиве до сортировки массива:

var
   item: ^TArrayItem;
   theArray: array[1..100] of TArrayItem;


item := @theArray[20];
SortTheArray(theArray);

Если это так, то после сортировки массива (или любой формы манипулирования этим массивом) значение указателя элемента может перестать быть надежным для динамического массива, поскольку массив мог перемещаться в памяти в результате операции, выполненные на нем!

Даже если массив не перемещался, как в настоящее время в случае статического массива, указатель элемента будет указывать на тот элемент, который сейчас находится на 20-й позиции в этом массиве, а не на элементе, который был в этой позиции до сортировки.

Другие вопросы по тегам