#массивы #delphi #pascal #enum #биоинформатика
Я могу задать в качестве индекса для массива последовательность литер алфавита, вот так:
type
ArRange = 'a'..'z';
var
ar: array[ArRange] of integer;
c:ArRange;
а затем использовать
for c:='a' to 'z' do
begin
i:=ar[c];
<...>
end;
Могу я как-то сузить диапазон алфавита, причём оставить из него только несколько
букв (конкретно A, G, T и C)? Как в этом случае определить ArRange и массив?
Ответы
Ответ 1
Не думаю, что это получится, поскольку буквы не идут по порядку. Я догадываюсь, зачем это вам :), но увы. Если это необходимо для построения дерева, можно пользоваться таким перечислением: type AGTCIndex = (A, C, G, T); Да, для сравнения с реальной последовательностью придётся сделать соответствие, например, посредством другого массива var lAGTC:array[AGTCIndex] of char = ('A','C','G','T'); и оперировать реальными строками уже через lAGTC[C] и т.п. Это всего лишь чуть дольше, чем у вас могло бы получиться. В любом случае, учитывайте, что и ord(char) и if (c = s[i]) тратят всего лишь несколько тактов CPU, поэтому не стоит пытаться сэкономить здесь, когда есть значительно более узкие бутылочные горлышки. Микрооптимизация, на мой взгляд, - бич современного прикладного программирования. Либо, если это нужно не для дерева или вам безразлично, сколько памяти отъедят ваши массивы, используйте type ArRange = 'A'..'T'; var ar: array[ArRange] of integer; и пользуйтесь только 4мя членами массива. Расточительно, разумеется.Ответ 2
Альтернативный вариант, для коллекции - эмуляция массива с помощью структуры. type TMyArr= record private FValues : array[0..3] of T; procedure setValue( c:char; v: T); inline; function getValue(c: char): T; inline; public property values[c : char]: T read getValue write setValue; default; end; Для 4х значений наиболее эффективней будет, наверное, вручную расставить индексы, не заморачиваясь с перечислениями. function TMyArr .getValue(c: char): T; begin case c of 'A' : result := FValues[0]; 'C' : result := FValues[1]; 'G' : result := FValues[2]; 'T' : result := FValues[3]; else raise EArgumentOutOfRangeException.Create(''); end; end; procedure TMyArr .setValue(c: char; v: T); var idx : byte; begin case c of 'A' : idx := 0; 'C' : idx := 1; 'G' : idx := 2; 'T' : idx := 3; else raise EArgumentOutOfRangeException.Create(''); end; FValues[idx] := v; end; В использовании от массива не отличается var data : TMyArr ; c : char; begin for c in ['A','C', 'G', 'T'] do begin data[c] := ord(c); writeln(data[c]); end; data['X'] := -1; //exception end. Ответ 3
Почему не использовать для этого словарь? Например, так: uses System.SysUtils, Vcl.Dialogs, System.Generics.Collections; var Dict: TDictionary; begin Dict := TDictionary .Create; try Dict.Add('A', 1); Dict.Add('G', 2); Dict.Add('T', 3); Dict.Add('C', 4); ShowMessage(IntToStr(Dict['T'])); finally Dict.Free; end; end. Можно еще, как вариант, написать наследника от TDictionary и в конструкторе инициализировать его нужными значениями.
Комментариев нет:
Отправить комментарий