Форум по Delphi программированию

Delphi Sources



Вернуться   Форум по Delphi программированию > Все о Delphi > [ "Начинающим" ]
Ник
Пароль
Регистрация <<         Правила форума         >> FAQ Пользователи Календарь Поиск Сообщения за сегодня Все разделы прочитаны

Ответ
 
Опции темы Поиск в этой теме Опции просмотра
  #1  
Старый 09.01.2017, 16:42
Мих123456 Мих123456 вне форума
Прохожий
 
Регистрация: 07.01.2017
Сообщения: 6
Версия Delphi: delphi 7
Репутация: 10
По умолчанию выбор операторов

Вариантов выбора очень много , более 100 , есть две переменные по которым надо будет выбрать
Если взять оператор if then , if (a=0) and (b=1) then то смущает что вариантов более ста. Но если взять
оператор Case of , то там проверка двух переменных нельзя, но он бы и работал быстрее. Подскажите есть
еще варианты для двух переменных? Или только if then ?
Ответить с цитированием
  #2  
Старый 09.01.2017, 17:06
Аватар для dr. F.I.N.
dr. F.I.N. dr. F.I.N. вне форума
I Like it!
 
Регистрация: 12.12.2009
Адрес: Россия, г. Новосибирск
Сообщения: 660
Версия Delphi: D6/D7
Репутация: 26643
По умолчанию

использовать простую ХЭШ функцию и оператор CASE
Код:
function MySimpleHash(a, b: Byte): Word;
begin
  Result := (a shl 8) or b;
end;

...
case MySimpleHash(a, b) of
...
...
...
...
end;
...
__________________
Грамотно поставленный вопрос содержит не менее 50% ответа.
Грамотно поставленная речь вызывает уважение, а у некоторых даже зависть.
Ответить с цитированием
  #3  
Старый 09.01.2017, 17:18
Мих123456 Мих123456 вне форума
Прохожий
 
Регистрация: 07.01.2017
Сообщения: 6
Версия Delphi: delphi 7
Репутация: 10
По умолчанию

Цитата:
Сообщение от dr. F.I.N.
использовать простую ХЭШ функцию и оператор CASE
Код:
function MySimpleHash(a, b: Byte): Word;
begin
  Result := (a shl 8) or b;
end;

...
case MySimpleHash(a, b) of
...
...
...
...
end;
...

Это сначало надо высчетать самому что переменные выдают?

Код:
begin
  ShowMessage(IntToStr(MySimpleHash(26, 49)));
case MySimpleHash(26, 49) of
 6705:ShowMessage('26-49');

end;


end;
Ответить с цитированием
  #4  
Старый 09.01.2017, 20:24
lmikle lmikle вне форума
Модератор
 
Регистрация: 17.04.2008
Сообщения: 8,003
Версия Delphi: 7, XE3, 10.2
Репутация: 49089
По умолчанию

можно высчитать, можно просто функцию попроще использовать:
Код:
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  
Старый 10.01.2017, 14:53
Аватар для M.A.D.M.A.N.
M.A.D.M.A.N. M.A.D.M.A.N. вне форума
Sir Richard Abramson
 
Регистрация: 05.04.2008
Сообщения: 5,505
Версия Delphi: XE10
Репутация: выкл
По умолчанию

Господа, вы это серьёзно?
Почему не так?
Код:
def is_passed(a, b, c, d):
    if a == c and b == d:
        return True
    else:
        return False
Ну и проверять на пересечении множеств (a, b).

Да ито, так слишком надумано, достаточно кортеж (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  
Старый 10.01.2017, 19:55
lmikle lmikle вне форума
Модератор
 
Регистрация: 17.04.2008
Сообщения: 8,003
Версия Delphi: 7, XE3, 10.2
Репутация: 49089
По умолчанию

Mad,
1. Изначально вопрос был в том, как не писать бесконечно длинный список if'ов. Ну и можно ли заменить его на case, если надо делать выбор по нескольким переменным. Базовый ответ - использовать хэш. Дальше я просто спроектировал чуть более гибкую системку, так, для фана.
2. Не знаю как остальные, а я просто уже начал "извращаться". Ну интересно мне было накидать макет такой маленькой подсиситемки.
Ответить с цитированием
Эти 3 пользователя(ей) сказали Спасибо lmikle за это полезное сообщение:
Admin (11.01.2017), dr. F.I.N. (11.01.2017), M.A.D.M.A.N. (10.01.2017)
  #7  
Старый 12.01.2017, 00:27
Аватар для Bargest
Bargest Bargest вне форума
Профессионал
 
Регистрация: 19.10.2010
Адрес: Москва
Сообщения: 2,390
Версия Delphi: XE3/VS12/FASM
Репутация: 14665
По умолчанию

Снова эти вопросы из категории "как закрутить шуруп ботинком" без объяснения "зачем это нужно и нужно ли вообще на самом деле".
Если приходится прописывать СТО условий в любом виде (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;
    }
}
(Фрагмент кода из реального java-приложения. Естественно, написан в поднебесной)
__________________
jmp $ ; Happy End!
The Cake Is A Lie.

Последний раз редактировалось Bargest, 12.01.2017 в 00:35.
Ответить с цитированием
Этот пользователь сказал Спасибо Bargest за это полезное сообщение:
lmikle (12.01.2017)
  #8  
Старый 12.01.2017, 01:12
lmikle lmikle вне форума
Модератор
 
Регистрация: 17.04.2008
Сообщения: 8,003
Версия Delphi: 7, XE3, 10.2
Репутация: 49089
По умолчанию

Bargest,

ТС, если не ошибаюсь, хотел именно "синтаксического сахара" для выбора дейсвия по 2м переменным. Ну ему накидали вариантов. Твой вариант с этой точки зрения еще менее удачный, т.к. настройку этой матрицы замучаешься писать и потом хрен прочитаешь (через пару-тройку месяцев). А как идея - да, не хуже моего варианта и даже писать чуть меньше.

Последний раз редактировалось lmikle, 12.01.2017 в 20:19.
Ответить с цитированием
  #9  
Старый 12.01.2017, 20:37
Аватар для Bargest
Bargest Bargest вне форума
Профессионал
 
Регистрация: 19.10.2010
Адрес: Москва
Сообщения: 2,390
Версия Delphi: XE3/VS12/FASM
Репутация: 14665
По умолчанию

[OFFTOP, продолжаем обсуждение упоротых вариантов]
Цитата:
т.к. настройку этой матрицы замучаешься писать
Её же совершенно не обязательно заполнять вручную . Сделать функцию Register(a, b, handler) и все. Решение почти совпадает с твоим, только учитывает, что по условию задачи, видимо, для каждой пары чисел не более 1 обработчика: не приходится для каждого обработчика вызывать
Код:
if CanExecute(a,b) then DoExecute(a,b);
Короче говоря, логика самой функции CanExecute просто вынесена на уровень выше, т.е. на уровень ExecuteDynamicAction в твоих терминах, что чуть быстрее (не полный перебор всех хендлеров, а бинарный поиск 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  
Старый 12.01.2017, 22:15
Аватар для M.A.D.M.A.N.
M.A.D.M.A.N. M.A.D.M.A.N. вне форума
Sir Richard Abramson
 
Регистрация: 05.04.2008
Сообщения: 5,505
Версия Delphi: XE10
Репутация: выкл
По умолчанию

Цитата:
Сообщение от Bargest
[OFFTOP, продолжаем обсуждение упоротых вариантов]
Вот я с тобой на 100% согласен, что лучше бы ТС описал стратегию решения задачи, а не просил улучшить тактику.

Вариантов решения масса. Тоже хотел подкинуть идею со словарём, да подумал, что не стоит разводить флейм.

З.Ы. Интересно, ТСу еще актуальна эта тема? А то от него фидбека нет.
__________________
— Как тебя понимать?
— Понимать меня не обязательно. Обязательно меня любить и кормить вовремя.


На Delphi, увы, больше не программирую.
Рекомендуемая литература по программированию
Ответить с цитированием
  #11  
Старый 13.01.2017, 00:29
lmikle lmikle вне форума
Модератор
 
Регистрация: 17.04.2008
Сообщения: 8,003
Версия Delphi: 7, XE3, 10.2
Репутация: 49089
По умолчанию

Цитата:
Сообщение от M.A.D.M.A.N.
Вот я с тобой на 100% согласен, что лучше бы ТС описал стратегию решения задачи, а не просил улучшить тактику.

Вариантов решения масса. Тоже хотел подкинуть идею со словарём, да подумал, что не стоит разводить флейм.

Идею со словарем тоже смотрел. Собственно, отказался, когда понял, что попадаешь на ограничение кол-ва параметров. Да, в коде я использовал всего 2, бо как такова постановка изначального вопроса. На самом деле там д.б. Pointer или TObject (ну а для новых версий вообще дженерик), через который и будет передаваться набор параметров (а может и array of const, все зависит от задачи). Ну это если все-таки мутить в сторону библиотеки.

Цитата:
Сообщение от M.A.D.M.A.N.
З.Ы. Интересно, ТСу еще актуальна эта тема? А то от него фидбека нет.

Мне кажется, что ТС просто офигел от дальнейшего обсуждения и сказать уже ничего не скажет. Хотя для той постановки задачи, которая была изначально, case по хеш функции вполне достаточно.
Ответить с цитированием
Ответ


Delphi Sources

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск
Опции просмотра

Ваши права в разделе
Вы не можете создавать темы
Вы не можете отвечать на сообщения
Вы не можете прикреплять файлы
Вы не можете редактировать сообщения

BB-коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.
Быстрый переход


Часовой пояс GMT +3, время: 13:37.


 

Сайт

Форум

FAQ

RSS лента

Прочее

 

Copyright © Форум "Delphi Sources" by BrokenByte Software, 2004-2023

ВКонтакте   Facebook   Twitter