perl6 User-defined comparison function in set opertions

冷暖自知 提交于 2019-12-10 02:56:31

问题


Perl6 documentation indicated that when comparing two items in a set, === is used. This is quote from perl6 documentation:

Objects/values of any type are allowed as set elements. Within a Set, every element is guaranteed to be unique (in the sense that no two elements would compare positively with the === operator)

I am wondering if it is possible to use a user-defined function instead of ===? E.g., How can I use ~~ instead of === in determining whether 2 elements in a set are "equal".

The problem I am trying to solve is this: set A has some first names and some last names in any order but all lower case and no punctuation, and set B has a number of first names and last names mixed in any order, and there may be punctuation attached to the names and may be upper or lower cases. I want to know if a person in set A (represented as a subset of A with one specific first and last name) appears in set B. In this case, I cannot use === because of the letter cases and punctuation in set B.

If I can use ~~ instead of ===, the problem will be much simpler because I only need to determine if a subset of A is also a subset of B using ~~. This is similar to a "permutation match" problem I mentioned before.

Thank you very much !


回答1:


There are a couple ways, and I'll start with the easy/slow way. I'll use the == operator, but you can use any operation. If you want to iterate over the list/set, you can use first with whatever match logic you like, then check for .defined to confirm that you got a match. (If you want to be really careful or if your list contains undefined items, you should use the :p adverb so your output is a key/value pair, and that will be defined if and only if some matching element was found.)

For an example of sloppy matching using this technique, I'll search for a number in a list and set of IntStr:

say 4 ∈ ("3", "4"); # False, because the list doesn't contain the integer 4
say ("3", "4").first(* == 4, :p).defined; # True
say set("3", "4").keys.first(* == 4, :p).defined; # True

You would have to benchmark to know whether this is as fast as checking set membership in a more conventional way. For a large set, the conventional ways should be faster, since hash lookup can be used. In some programming languages, iteration is faster than hashing until the list gets really big.

If you don't need to get the matching element, you can use junctions, which will do multiple checks in parallel:

say so ("3", "4").any() == 4; # True

And you can use junctions to do subset testing as well, but since this is an O(m*n) operation (despite being auto-threaded), don't expect high performance when comparing two very large sets.

say so (2, 3).all() == ('1', '2', '3').any(); # True
say so (2, 3, 4).all() == ('1', '2', '3').any(); # False

I used lists instead of sets above, since if you're not using the standard operators/methods, sets offer no speed or API advantage.



来源:https://stackoverflow.com/questions/47667461/perl6-user-defined-comparison-function-in-set-opertions

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!