понедельник, декабря 5

Lotus @-формулы. задачки

Имеем на входе представление с 3-мя колонками:
1) список А (например пользователей)
2) список Б (например ролей)
3) список В (отношение пользователь-роль)

Задача: Выбрать уникальные роли из колонки Б, которые есть у всех пользователей из колонки А. При этом, если роль не встречается хотя бы у одного пользователя, то её отбрасываем.

в итоге родилось вот такое вот решение на @-формулах (переменные list, roles и users как бы результат выборки из представления):

list := "User1~role1":"User2~role3":"User2~role1":"User3~role1":"User3~role3":"User4~role1":"User4~role2";
roles:="role1":"role2":"role3";
users := "User1":"User2":"User3":"User4";

t0:=users*+"~"*+roles;
t1:=@Replace(t0; list; "");
t2:=@Explode(t1; "~");
t3:=@Replace(t2; roles; "");
t4:=@Unique(@Replace(t2; t3; ""));
result := @Unique(@Replace(roles; t4; ""));
result

Результат вычисления: role1


А теперь по порядку распишу каждую строчку:

создаём все возможные пересечения пользователь~роль
t0:=users*+"~"*+roles;
User1~role1
User1~role2
User1~role3
User2~role1
User2~role2
User2~role3
User3~role1
User3~role2
User3~role3
User4~role1
User4~role2
User4~role3

удаляем все пересечения, которые уже есть в list:
t1:=@Replace(t0; list; "");
User1~role2
User1~role3
User2~role2
User3~role2
User4~role3

Преобразуем список t1 в список с пользователями и ролями отдельно в каждой "строке"
t2:=@Explode(t1; "~");
User1
role2
User1
role3
User2
role2
User3
role2
User4
role3

удаляем из списка t2 все роли, оставляя только пользователей
t3:=@Replace(t2; roles; "");
User1
User1
User2
User3
User4

А теперь из списка t2 удаляем всех пользователей, полученных в списке t3. Тем самым мы получаем роли, которые не упоминались у каждого из пользователя в списке users
t4:=@Unique(@Replace(t2; t3; ""));
role2
role3

ну и завершающий аккорд - "инвертирование" списка t4, оставляя только те роли из списка roles, которые не попали в t4
result := @Unique(@Replace(roles; t4; ""));
role1



UPD: Формулу можно сократить и привести к следующей:


t0:=users*+"~"*+roles;
t1:=@Replace(t0; list; "");
t2:=@Unique(@Right(t1;"~"));
result := @Trim(@Unique(@Replace(roles; t2; "")));
result