|
#1
|
|||
|
|||
выбор операторов
Вариантов выбора очень много , более 100 , есть две переменные по которым надо будет выбрать
Если взять оператор if then , if (a=0) and (b=1) then то смущает что вариантов более ста. Но если взять оператор Case of , то там проверка двух переменных нельзя, но он бы и работал быстрее. Подскажите есть еще варианты для двух переменных? Или только if then ? |
#2
|
||||
|
||||
использовать простую ХЭШ функцию и оператор CASE
Код:
function MySimpleHash(a, b: Byte): Word; begin Result := (a shl 8) or b; end; ... case MySimpleHash(a, b) of ... ... ... ... end; ... Грамотно поставленный вопрос содержит не менее 50% ответа. Грамотно поставленная речь вызывает уважение, а у некоторых даже зависть. |
#3
|
|||
|
|||
Цитата:
Это сначало надо высчетать самому что переменные выдают? Код:
begin ShowMessage(IntToStr(MySimpleHash(26, 49))); case MySimpleHash(26, 49) of 6705:ShowMessage('26-49'); end; end; |
#4
|
|||
|
|||
можно высчитать, можно просто функцию попроще использовать:
Код:
function MyCalcHash(a, b : byte) : Integer; begin Result := a*1000 + b; end; Код:
MyCalcHash(1,1) = 1001 MyCalcHash(10,8) = 10008 и т.д. А вообще, я бы подумал над динамическим выполением этого условия. Все, конечно, зависит от того, что конкретно надо делать в зависимости от значений a & b. Если просто присвоить значение какой-нить переменной или вызвать СТАНДАРТНУЮ функцию, то городить огород смыла нет. А вот если надо выполнить свой код, причем довольно объемный, да еще и в программе этот case при стандартном сценарии использования исполняется многократно, то тогда можно заморочиться с более динамической штукой. Как сделать: 1. Пишем базовый класс: Код:
interface type TDynamicActionBase = class protected procedure DoExecute; virtual; abstract; function CanExecute(a, b : byte) : Boolean; virtual; abstract; public function Execute(a, b : byte): Boolean; procedure Register(AList : TObjectList); end; implementation procedure TDynamicActionBase.Register(AList : TObjectList); begin AList.Add(Self); end; function TDynamicActionBase.Execute(a, b : Byte) : Boolean; begin Result := CanExecute(a,b); If Result Then DoExecute; end; 2. Теперь для каждого реального действия "рожаем" наследника и перекрываем у него соотв. методы: Код:
interface type TDynamicAction_1_1 = class(TDynamicActionBase) protected procedure DoExecute; override; function CanExecute(a, b : byte) : Boolean; override; end; TDynamicAction_2_2 = class(TDynamicActionBase) protected procedure DoExecute; override; function CanExecute(a, b : byte) : Boolean; override; end; implementation procedure TDynamicAction_1_1.DoExecute; begin ShowMessage('1-1'); // Просто для демонстрации end; function TDynamicAction_1_1.CanExecute(a, b : byte) : Boolean; begin Result := (a = 1) and (b = 1); end; procedure TDynamicAction_2_2.DoExecute; begin ShowMessage('2-2'); // Просто для демонстрации end; function TDynamicAction_2_2.CanExecute(a, b : byte) : Boolean; begin Result := (a = 2) and (b = 2); end; 3. Теперь нам надо наши классы зарегистрировать в списке: Код:
interface var DynamicActionList : TObjectList; initialization DynamicActionList := TObjectList.Create(True); TDynamicAction_1_1.Create.Register(DynamicActionList); TDynamicAction_2_2.Create.Register(DynamicActionList); finalization FreeAndNil(DynamicActionList); end. 4. Ну и последний штрих. Надо написать процедуру-выполнятель (функцию, если ничего не нашлось, то она вернет False, если что-то нашлось - то True) Код:
interface function ExecuteDynamicAction(a,b : byte) : Boolean; implementation function ExecuteDynamicAction(a,b : byte) : Boolean; var I : Integer; begin Result := False; For I := 0 To DynamicActionList.Count-1 Do begin Result := (DynamicActionList[i] As TDynamicActionBase).Execute(a,b); If Result Then Break; end; end; ЗЫ. Если хочется действия развести по разным модулям, то тогда прямое обращение к списку действий надо заменить на использование фабрики, а описание DynamicActionList перенести в секцию implementation. DynamicActionList д.б. синглтоном. Последний раз редактировалось lmikle, 09.01.2017 в 23:17. |
#5
|
||||
|
||||
Господа, вы это серьёзно?
Почему не так? Код:
def is_passed(a, b, c, d): if a == c and b == d: return True else: return False Да ито, так слишком надумано, достаточно кортеж (a, b) проверить на вхождение в список кортежей возможных вариантов. Код:
>>> foo = [(1, 2), (3, 4), (5, 6)] >>> foo [(1, 2), (3, 4), (5, 6)] >>> a = (3, 4) >>> a in foo True >>> (1, 2) in foo True >>> (1, 3) in foo False З.Ы. Собственно Финн дал код той же сути, только он оперировал произведением чисел, а не кортежем. — Как тебя понимать? — Понимать меня не обязательно. Обязательно меня любить и кормить вовремя. На Delphi, увы, больше не программирую. Рекомендуемая литература по программированию Последний раз редактировалось M.A.D.M.A.N., 10.01.2017 в 14:59. |
#6
|
|||
|
|||
Mad,
1. Изначально вопрос был в том, как не писать бесконечно длинный список if'ов. Ну и можно ли заменить его на case, если надо делать выбор по нескольким переменным. Базовый ответ - использовать хэш. Дальше я просто спроектировал чуть более гибкую системку, так, для фана. 2. Не знаю как остальные, а я просто уже начал "извращаться". Ну интересно мне было накидать макет такой маленькой подсиситемки. |
Эти 3 пользователя(ей) сказали Спасибо lmikle за это полезное сообщение: | ||
#7
|
||||
|
||||
Снова эти вопросы из категории "как закрутить шуруп ботинком" без объяснения "зачем это нужно и нужно ли вообще на самом деле".
Если приходится прописывать СТО условий в любом виде (if или case), то с большой вероятностью задача решается в корне неверно. Например, решение "в лоб" (альтернатива решению lmikle): делаем 2 массива возможных значений A и B, и матрицу M с обработчиками размера A.length x B.length, где M[i, j] = executor при A[i] = a и B[j] = b. Если A[a] = a и B[b] = b, то решение выродится в простое взятие по индексу M[a, b]. Можно и лучше сделать, если знать, зачем все это. Но, конечно, если хочется познать дзен китайского кода - тогда согласен, вопрос "зачем" задавать нельзя. Код:
public int a(int v) { switch (v) { case 0: return 0; case 1: return 1; case 2: return 2; case 3: return 3; case 4: return 4; // ... case 255: return 255; default: return -1; } } jmp $ ; Happy End! The Cake Is A Lie. Последний раз редактировалось Bargest, 12.01.2017 в 00:35. |
Этот пользователь сказал Спасибо Bargest за это полезное сообщение: | ||
lmikle (12.01.2017)
|
#8
|
|||
|
|||
Bargest,
ТС, если не ошибаюсь, хотел именно "синтаксического сахара" для выбора дейсвия по 2м переменным. Ну ему накидали вариантов. Твой вариант с этой точки зрения еще менее удачный, т.к. настройку этой матрицы замучаешься писать и потом хрен прочитаешь (через пару-тройку месяцев). А как идея - да, не хуже моего варианта и даже писать чуть меньше. Последний раз редактировалось lmikle, 12.01.2017 в 20:19. |
#9
|
||||
|
||||
[OFFTOP, продолжаем обсуждение упоротых вариантов]
Цитата:
Код:
if CanExecute(a,b) then DoExecute(a,b); Можно построить то же самое не на двумерном массиве, а на каком-нибудь TDictionary<int, TDictionary<int, Handler>>, если в возможных значениях много неиспользуемых пар. Тогда просто вызывается handlers[a][b]() и ловится эксепшен, если обработчика нет. Короче, вариантов может быть много. jmp $ ; Happy End! The Cake Is A Lie. Последний раз редактировалось Bargest, 12.01.2017 в 20:40. |
#10
|
||||
|
||||
Цитата:
Вариантов решения масса. Тоже хотел подкинуть идею со словарём, да подумал, что не стоит разводить флейм. З.Ы. Интересно, ТСу еще актуальна эта тема? А то от него фидбека нет. — Как тебя понимать? — Понимать меня не обязательно. Обязательно меня любить и кормить вовремя. На Delphi, увы, больше не программирую. Рекомендуемая литература по программированию |
#11
|
|||
|
|||
Цитата:
Идею со словарем тоже смотрел. Собственно, отказался, когда понял, что попадаешь на ограничение кол-ва параметров. Да, в коде я использовал всего 2, бо как такова постановка изначального вопроса. На самом деле там д.б. Pointer или TObject (ну а для новых версий вообще дженерик), через который и будет передаваться набор параметров (а может и array of const, все зависит от задачи). Ну это если все-таки мутить в сторону библиотеки. Цитата:
Мне кажется, что ТС просто офигел от дальнейшего обсуждения и сказать уже ничего не скажет. Хотя для той постановки задачи, которая была изначально, case по хеш функции вполне достаточно. |