#comparison #wolfram-mathematica #rules
#сравнение #wolfram-mathematica #Правила
Вопрос:
Мне нужно сравнить два списка правил формы var -> integer
по факту несоответствия.
Чтобы определить, есть ли какие-либо правила, одинаковые по lhs и разные по rhs.
Например:
{a-> 3, b-> 1, c-> 4} ~ ??? ~ {a->3, b-> 1, c-> 4} = true
{a->3, b-> 1, c-> 4} ~ ??? ~ {a->3, b-> 2, c-> 4} = false
{a->3, b-> 1, c-> 4} ~ ??? ~ {a->1, b-> 3, c-> 4} = false
{a->3, b-> 1, c-> 4} ~ ??? ~ {c->4, d-> 8, e-> 9} = true
{a-> 3, b-> 1, c-> 4} ~ ??? ~ {d-> 8, e-> 9, f-> 7} = true
В моем случае они уже отсортированы по lhs, и все lhs уникальны, если это может помочь сделать как можно более простую функцию.
UPD: забыл одну вещь! Списки могут быть разной длины. Но, похоже, все три текущих ответа все еще действительны.
Ответ №1:
Вот еще одно решение:
In[12]:= check[a:{__Rule}, b:{__Rule}] := FilterRules[a, b] === FilterRules[b, a]
In[18]:= {{a -> 3, b -> 1, c -> 4}~check ~ {a -> 3, b -> 1, c -> 4} ,
{a -> 3, b -> 1, c -> 4}~check ~ {a -> 3, b -> 2, c -> 4},
{a -> 3, b -> 1, c -> 4}~check ~ {a -> 1, b -> 3, c -> 4},
{a -> 3, b -> 1, c -> 4}~check ~ {c -> 4, d -> 8, e -> 9},
{a -> 3, b -> 1, c -> 4}~check ~ {d -> 8, e -> 9, f -> 7}}
Out[18]= {True, False, False, True, True}
(Это зависит от того факта, что списки параметров уже отсортированы.)
Комментарии:
1. В дополнение к размеру, это решение в 3 раза быстрее для моих данных, чем два других.
2. @Nakilon Если скорость является проблемой, перенесите правила в r.h.s. из
/.
inDispatch
— это должно ускорить код, как для моей версии (версий), так и для @Heike.
Ответ №2:
Вы могли бы сделать что-то вроде
check[{a__Rule}, {b__Rule}] :=
Module[{common = Intersection[{a}[[All, 1]], {b}[[All, 1]]]},
SameQ[common /. {a}, common /. {b}]]
Затем
check[{a -> 3, b -> 1, c -> 4}, {a -> 3, b -> 1, c -> 4}]
check[{a -> 3, b -> 1, c -> 4}, {a -> 3, b -> 2, c -> 4}]
check[{a -> 3, b -> 1, c -> 4}, {a -> 1, b -> 3, c -> 4}]
дает
True
False
False
Комментарии:
1. 1 Это именно тот подход, который я придумал (но через полчаса после вас!).
2. 1 Это решение можно легко обобщить для пустых наборов правил, заменив
BlankSequence
(__
) наBlankNullSequence
(___
):check[{a___Rule}, {b___Rule}] := ...
.3. В чем разница между
check[{a__Rule}, {b__Rule}] :=
иcheck[a, b] :=
?4. @Nakilon Пожалуйста, прочтите соответствующие страницы документации: » Создание определений для функций «, »
Blank
(_
) «, »BlankSequence
(__
) «.
Ответ №3:
Возможно, проще
check[a : {__Rule}, b : {__Rule}] := SameQ @@ Transpose[a /. b /. a /. Rule -> List]
Редактировать
Вот еще более эзотерическая версия, преимущество которой в том, что она полностью высокоуровневая, в том смысле, что нам не нужно ничего знать о внутренней структуре правил, только о том, как они действуют:
checkAlt[a : {__Rule}, b : {__Rule}] := # === (# /. #) amp;[a /. b /. a]
РЕДАКТИРОВАТЬ 2
Что ж, позвольте мне добавить еще один, просто для удовольствия:
check1[{a__Rule}, {b__Rule}] := SameQ @@ ({a, b} /. {{a, b}, {b, a}})
Комментарии:
1. @Nakilon Идея в том, что мы действуем с правилами из
b
l.h.s ofa
. Это предполагает, что в r.h.s нет переменныхa
. Например, еслиa
есть{c->1,d->2,e->3}
иb
есть{c->1,d->3,f->4}
, вы получаете дляa/.b
этого:{1->1,2->3,e->4}
. Теперь мы действуем сa
, так что те переменные, которых нет вb
l.h.s. , также будут заменены. Тогда вы получаете{1->1,2->3,4->4}
. Чтобы наборы правил были одинаковыми, стандартные и стандартные правила должны быть одинаковыми. Это проверяется остальной частью кода, где правила сначала преобразуются во вложенные списки.2. @Alexey Действительно, моя версия не очень общая. Я использовал спецификацию OP: правила ограничены формой
var->int
, но это будет работать также во всех случаях, когда в r.h.s нет переменных.3. @Alexey Если мы получим список таких незанятых правил
{1->1,2->2}
, то он не изменится, когда мы будем действовать с ним самостоятельно. Если у нас есть список, в котором некоторые правила не простаивают, как, скажем{1->1,2->3,3->3}
, тогда список обязательно изменится, когда мы будем действовать с ним с помощью функции itself (#/.#
) , что также кажется довольно простым для просмотра, потому что те же самые lh.стороны, которые отличаются, будут заменены их rh. сторонами, предоставляя другой список правил.4. @Leonid Ой! Это поведение задокументировано в поле «Дополнительная информация». Извините за путаницу.
5. @Alexey О, но это так, хотя и в учебном пособии, а не на странице функций: ссылка. wolfram.com/mathematica/tutorial /…
Ответ №4:
Вот немного обобщенный подход:
In[24]:= check[lists__] :=
And @@ (SameQ @@@ GatherBy[Join[lists], First])
In[25]:= {
{a -> 3, b -> 1, c -> 4}~check~{a -> 3, b -> 1, c -> 4},
{a -> 3, b -> 1, c -> 4}~check~{a -> 3, b -> 2, c -> 4},
{a -> 3, b -> 1, c -> 4}~check~{a -> 1, b -> 3, c -> 4},
{a -> 3, b -> 1, c -> 4}~check~{c -> 4, d -> 8, e -> 9},
{a -> 3, b -> 1, c -> 4}~check~{d -> 8, e -> 9, f -> 7}
}
Out[25]= {True, False, False, True, True}
Для этого не требуется, чтобы элементы были правилами, они могут быть списками или практически любым другим заголовком. Он также должен работать с любым количеством входных данных.