I wrote one I modeled after the old Clipper
AScan
function (tested in XE
). @RRUZ’s answer is more correct (there is one existing), but mine doesn’t require the array to be sorted first and is fast enough on small arrays. (It also works in pre-generics versions of Delphi.) I also overload it for various types of array – here are the implementations for string
and integer
:
// Returns the 0-based index of Value if it's found in the array,
// -1 if not. (Similar to TStrings.IndexOf)
function AScan(const Ar: array of string; const Value: string): Integer; overload;
var
i: Integer;
begin
Result := -1;
for i := Low(Ar) to High(Ar) do
if SameText(Ar[i], Value) then
begin
Result := i;
Break
end;
end;
function AScan(const Ar: array of Integer; const Value: Integer): Integer; overload;
var
i: Integer;
begin
Result := -1;
for i := Low(Ar) to High(Ar) do
if (Ar[i] = Value) then
begin
Result := i;
Break
end;
end;
procedure TForm2.FormShow(Sender: TObject);
var
someStrArray: TArray<string>;
someIntArray: TArray<Integer>;
Idx: Integer;
begin
someStrArray := TArray<string>.Create('One', 'Two', 'Three');
Idx := AScan(someStrArray, 'Two');
if Idx > -1 then
ShowMessage(Format('It contains Two at index %d', [Idx]))
else
ShowMessage('Not found');
someIntArray := TArray<Integer>.Create(8, 16, 32);
Idx := AScan(someIntArray, 32);
if Idx > -1 then
ShowMessage(Format('It contains 32 at %d', [Idx]))
else
ShowMessage('16 not found');
end;
For versions of Delphi that support generics, here’s a version that doesn’t require the array to be sorted, and that also allows you to provide the comparison function if needed:
Interface:
type
TGenericsUtils = class
public
class function AScan<T>(const Arr: array of T; const Value: T; const Comparer: IEqualityComparer<T>): Integer; overload;
class function AScan<T>(const Arr: array of T; const Value: T): Integer; overload;
end;
Implementation
class function TGenericsUtils.AScan<T>(const Arr: array of T; const Value: T): Integer;
begin
Result := AScan<T>(Arr, Value, TEqualityComparer<T>.Default);
end;
class function TGenericsUtils.AScan<T>(const Arr: array of T; const Value: T;
const Comparer: IEqualityComparer<T>): Integer;
var
i: Integer;
begin
for i := Low(Arr) to High(Arr) do
if Comparer.Equals(Arr[i], Value) then
Exit(i);
Exit(-1);
end;
Test code:
var
AIntTest: TIntegerDynArray;
AStrTest: TStringDynArray;
begin
AIntTest := TIntegerDynArray.Create(12, 15, 6, 1, 4, 9, 5);
AStrTest := TStringDynArray.Create('One', 'Six', 'Three', 'Four', 'Twelve');
WriteLn('AIntTest contains 9 at index ', TGenericsUtils.AScan<Integer>(AIntTest, 9));
WriteLn('AStrTest contains ''Four'' at index ', TGenericsUtils.AScan<String>(AStrTest, 'Four'));
ReadLn;
end.
You could also write a Generic version, however you can’t use generics with stand-alone procedures, they need to be bound to a class or record. Something like the following
unit Generics.ArrayUtils;
interface
uses
System.Generics.Defaults;
type
TArrayUtils<T> = class
public
class function Contains(const x : T; const anArray : array of T) : boolean;
end;
implementation
{ TArrayUtils<T> }
class function TArrayUtils<T>.Contains(const x: T; const anArray: array of T): boolean;
var
y : T;
lComparer: IEqualityComparer<T>;
begin
lComparer := TEqualityComparer<T>.Default;
for y in anArray do
begin
if lComparer.Equals(x, y) then
Exit(True);
end;
Exit(False);
end;
end.
usage would be
procedure TForm6.Button1Click(Sender: TObject);
begin
if TArrayUtils<integer>.Contains(3, [1,2,3]) then
ShowMessage('Yes')
else
ShowMessage('No');
end;
Should work with parameters like TArray<integer>
or array of integer
as well as constant arrays (shown) – and you could add many other methods to the class, such as IndexOf
or Insert
…
From Delphi 10.3 you can omit the <integer>
due to type inferencing so would look like TArrayUtils.Contains(3, [1,2,3])
.
beginner03 0 / 0 / 0 Регистрация: 11.06.2020 Сообщений: 73 |
||||
1 |
||||
Найти элемент в массиве26.06.2020, 07:27. Показов 1062. Ответов 9 Метки нет (Все метки)
Не находит введенное число. Где ошибка ?
0 |
668 / 558 / 242 Регистрация: 26.11.2012 Сообщений: 2,190 |
|
26.06.2020, 08:50 |
2 |
a[i]=obr Чему равно obr?
0 |
Нарушитель 8584 / 4589 / 1058 Регистрация: 12.03.2015 Сообщений: 21,524 |
|
26.06.2020, 08:55 |
3 |
Прогони под отладчиком – сразу найдёшь.
0 |
0 / 0 / 0 Регистрация: 11.06.2020 Сообщений: 73 |
|
26.06.2020, 09:03 [ТС] |
4 |
Изначально в Edit1 в Text указано произвольное число. Ввожу любое из матрицы, не видит. Как инициализировать obr ?
0 |
AzAtom Модератор 3366 / 1939 / 705 Регистрация: 15.11.2015 Сообщений: 7,716 |
||||
26.06.2020, 09:07 |
5 |
|||
Как инициализировать obr ? Эти строки как бы намекают, как инициализировать эту переменную:
Зачем нужно было удалять инициализацию obr?
0 |
0 / 0 / 0 Регистрация: 11.06.2020 Сообщений: 73 |
|
26.06.2020, 09:17 [ТС] |
6 |
ранее уже присваивал 0, но всё равно не работает. Добавлено через 6 минут
0 |
0 / 0 / 0 Регистрация: 11.10.2021 Сообщений: 2 |
|
10.10.2022, 06:43 |
7 |
Брат пж мне помаги можешь этот проект скинуть пж брат
0 |
Модератор 3366 / 1939 / 705 Регистрация: 15.11.2015 Сообщений: 7,716 |
|
10.10.2022, 09:54 |
8 |
Hasan6, человек уже год не заходил на форум. Что здесь есть, то и бери.
0 |
0 / 0 / 0 Регистрация: 11.10.2021 Сообщений: 2 |
|
10.10.2022, 09:57 |
9 |
Я не знаю как эту ошибку исправить пж помаги буду благадарен
0 |
mr-Crocodile 2876 / 1532 / 618 Регистрация: 19.03.2019 Сообщений: 5,115 |
||||
10.10.2022, 10:15 |
10 |
|||
Я не знаю как эту ошибку исправить какую – “эту” ? ну и начни всё же с такого кода:
1 |
IT_Exp Эксперт 87844 / 49110 / 22898 Регистрация: 17.06.2006 Сообщений: 92,604 |
10.10.2022, 10:15 |
Помогаю со студенческими работами здесь В массиве найти последний отрицательный элемент В массиве из случайных чисел найти наибольший элемент В заданном одномерном массиве найти последний отрицательный элемент Найти наибольший элемент и его индексы в двумерном массиве Есть вот такой код: В одномерном массиве Х найти максимальный элемент среди положительных Найти наибольший отрицательный и наименьший элемент в одномерном массиве Искать еще темы с ответами Или воспользуйтесь поиском по форуму: 10 |
Delphi DevTips
Delphi development tips from real-life projects (yes those do exist!!!)
So the problem appeared today, when I wanted to see if a specific integer number appeared in an array of integers. Ok this feels a little bit too general, so let’s see the real life case.
I have a table with transportation vehicles where each vehicle is of specific type. Each vehicle type in the database is represented through an number(10) value which as you might understand it is a foreign key to another table. The request was to make a checking about specific data only when a vehicle is of specific types. Let’s say that those types are 1, 2, 3, 4, 7, 9, 10.
Having this in mind I decided to create a function that will find the vehicle type of a specific vehicle (this is not what it needs to be seen right now – meaning the select statements etc) and to check whether this type is one of the types the checking will take place.
To do this a function is created called VehicleIsSpecificType which will return a boolean and does the following:
function VehicleIsSpecificType(VehicleCodeId: Integer): Boolean; var VehType: Variant; i: Integer; const ValidTypesForChecking: array[0..6] of Integer = (1, 2, 3, 4, 7, 9, 10); begin Result := False; {First find the vehicle type through the use of a select statement. Not shown here as it's part of a specific ERP SDK} VehType := .....; //returned a Variant if not VarIsNull(VehType) then for i := 0 to Length(ValidTypesForChecking) - 1 do if i = VehType then begin Result := True; break; end; end;
Of course the same thing can be done with other element types like strings or float values. Even with multidimensional arrays (which a second for loop will be needed – it will be shown in a future post)
Очень был удивлен когда к нам поступила
просьба рассказать о массивах и о их
сортировке в Delphi. Но раз уж поступила
просьба, а сайт наш призван помочь в
освоении Delphi, то я решил написать эту статью,
в которой расскажу Вам о возможных
действиях с массивами в Delphi. При этом мы
напишем несколько пользовательских
функций, которые будут помогать нам в
дальнейшем при работе с массивами.
Ввод массива
Для того чтобы работать с массивом, его
надо с начала получить от пользователя.
Попробуем осуществить ввод одномерного
массива всего в одно поле редактирования.
Каждый элемент массива будет отделяться от
предыдущего разделителем. После щелчка на
кнопке программа выделит из строки,
содержащей массив, первую подстроку,
затем выделит вторую подстроку и т.д.
Давайте сейчас этим и займемся. Поставьте
на Вашу форму кнопку Button и поле
редактирования Edit.
Заголовок нашей функции будет такой:
function GetSubStr(st:string; expl:string; n:integer):string;
где
st – строка, содержащая массив
expl – строка разделитель
n – номер подстроки
function TForm1.GetSubStr(st:string; expl:string ;n:integer):string; Var p,i:integer; Begin for i:= 1 to n-1 do begin p:=pos(expl,st); st:=copy(st,p+1,Length(st)-p); while (pos(expl,st)=1) and (length(st)>0) do delete(st,1,1); end; p:=pos(expl,st); if p<>0 then result:=copy(st,1,p-1) else result:=st; End;
Для получения n-ой подстроки (элемента
массива) из полученной в качестве аргумента
строки функция сначала удаляет
предшествующую ей n-1 подстроку (цикл for),
затем находит разделитель, который
обозначает конец нужной подстроки,
выделяет подстроку и возвращает ее в
качестве значения функции (через свое имя).
Не забудьте добавить заголовок нашей
функции в раздел Public модуля программы.
Теперь для проверки работы нашей функции
напишем обработчик события OnClick, для
нашей кнопки. В начале мы с помощью нашей
функции получим массив из Edit1, а потом
выведем его:
procedure TForm1.Button1Click(Sender: TObject); var i:integer; a:array[1..10] of string[10]; st:string; begin for i:=1 to 10 do a[i]:=GetSubStr(Edit1.text,' ',i);//используем пробел в качестве разделителя for i:=1 to 10 do st:=st+IntTostr(i)+' '+a[i]+#13; ShowMessage(st); end;
Поиск минимального (максимального)
элемента массива
Будем искать минимальный элемент в
целочисленном массиве. Для этого немного
изменим обработчик события OnClick для
кнопки:
procedure TForm1.Button1Click(Sender: TObject); var i:integer;//номер элемента, сравниваемого с минимальным a:array[1..10] of integer; min:integer;//номер минимального элемента begin //Введем массив for i:=1 to 10 do //Преобразуем полученные подстроки в числа a[i]:=StrToInt(GetSubStr(Edit1.text,' ',i));//используем пробел в качестве разделителя //Найдем минимальный элемент min:=1; //пусть номер минимального элемента = 1 for i:= 2 to 10 do // начнем искать со следующего if a[i] < a[min] then min:=i; Form1.caption:=IntToStr(a[min]); // выводим в заголовок формы минимальный элемент end;
В этом примере a[min] минимальный
элемент массива, а min – номер
минимального элемента. Алгоритм очень
простой: сравниваем каждый следующий
элемент с минимальным, если он меньше
минимального, то запоминаем его номер в
переменной min, и продолжаем сравнивать
уже с ним.
Чтобы найти максимальный
элемент, нужно изменить всего одну строку:
>>> if a[i] < a[min] then min:=i;
Надо заменить на:
if a[i] > a[min] then min:=i;
Только теперь a[min] – максимальный элемент,
а min – номер максимального элемента.
Поиск заданного элемента в массиве
Поступим методом простого перебора. Для
этого будем перебирать все элементы
массива, пока не встретим искомый элемент,
или пока не дойдем до конца массива.
Элемент,
совпадение с которым нам надо найти будем
хранить в текстовом поле Edit2. Обработчик
события OnClick нашей кнопки будет иметь такой
вид:
procedure TForm1.Button1Click(Sender: TObject); var i:integer; a:array[1..10] of integer; n:integer;//образец found:boolean; begin //Введем массив for i:=1 to 10 do //Преобразуем полученные подстроки в числа a[i]:=StrToInt(GetSubStr(Edit1.text,' ',i));//используем пробел в качестве разделителя n:=StrToInt(Edit2.text); found:=false; i:=1; REPEAT if a[i] = n then found:=true else i:=i+1; UNTIL (i > 10) or (found = true); if found then showmessage('Совпадение с элементом номер '+IntToStr(i)); end;
Сортировка массива
Вот мы и дошли до самого интересного – до
сортировки массива. Рассмотрим алгоритм т.н.
прямого выбора. Смысл его заключается в
следующем:
Просматривая массив от первого элемента,
найдем минимальный элемент и поместим его
на место первого элемента, а первый
элемент – на место минимального.Затем будем просматривать массив,
начиная со второго элемента, и далее
поступим, как поступили перед этим
шагом.
Алгоритм ясен, теперь приступим к
написанию кода. Все тот же обработчик
события OnClick принимает теперь такой вид:
procedure TForm1.Button1Click(Sender: TObject); var i,k,j,min:integer; buf:integer; // буфер для обмена a:array[1..10] of integer; st:string; begin //введем массив for i:=1 to 10 do a[i]:=StrToInt(GetSubStr(Edit1.text,' ',i));//используем пробел в качестве разделителя for i:=1 to 10 - 1 do // кол-во элементов минус один begin //поищем минимальный элемент min:=i; for j:=i+1 to 10 do if a[j] < a[min] then min:=j; //поменяем местами buf:=a[i]; a[i]:=a[min]; a[min]:=buf; end; for k:=1 to 10 do Form1.Caption:=Form1.caption + ' '+ IntToStr(a[k]); end;
Ну вот мы и познакомились с самыми
типичными действиями с массивами. Надеюсь
эта статья оказалась Вам хоть немного
полезной 🙂