1List::Compare::FunctionUasle(r3)Contributed Perl DocumenLtiastti:o:nCompare::Functional(3)
2
3
4
6 List::Compare::Functional - Compare elements of two or more lists
7
9 This document refers to version 0.55 of List::Compare::Functional.
10 This version was released August 16 2020. The first released version
11 of List::Compare::Functional was v0.21. Its version numbers are set to
12 be consistent with the other parts of the List::Compare distribution.
13
14 Notice of Interface Changes
15 Certain significant changes to the interface to
16 List::Compare::Functional were made with the introduction of Version
17 0.25 in April 2004. The documentation immediately below reflects those
18 changes, so if you are first using this module with that or a later
19 version, simply read and follow the documentation below. If, however,
20 you used List::Compare::Functional prior to that version, see the
21 discussion of interface changes farther below: April 2004 Change of
22 Interface.
23
25 Getting Started
26 List::Compare::Functional exports no subroutines by default.
27
28 use List::Compare::Functional qw(:originals :aliases);
29
30 will import all publicly available subroutines from
31 List::Compare::Functional. The model for importing just one subroutine
32 from List::Compare::Functional is:
33
34 use List::Compare::Functional qw( get_intersection );
35
36 It will probably be most convenient for the user to import functions by
37 using one of the two following export tags:
38
39 use List::Compare::Functional qw(:main :mainrefs);
40
41 The assignment of the various comparison functions to export tags is
42 discussed below.
43
44 For clarity, we shall begin by discussing comparisons of just two lists
45 at a time. Farther below, we shall discuss comparisons among three or
46 more lists at a time.
47
48 Comparing Two Lists Held in Arrays
49 • Given two lists:
50
51 @Llist = qw(abel abel baker camera delta edward fargo golfer);
52 @Rlist = qw(baker camera delta delta edward fargo golfer hilton);
53
54 • Get those items which appear at least once in both lists (their
55 intersection).
56
57 @intersection = get_intersection( [ \@Llist, \@Rlist ] );
58
59 Note that you could place the references to the lists being
60 compared into a named array and then pass "get_intersection()" a
61 reference to that array.
62
63 @to_be_compared = ( \@Llist, \@Rlist );
64 @intersection = get_intersection( \@to_be_compared );
65
66 Beginning with version 0.29 (May 2004), List::Compare::Functional
67 now offers an additional way of passing arguments to its various
68 functions. If you prefer to see a more explicit delineation among
69 the types of arguments passed to a function, pass a single hash
70 reference which holds the lists being compared in an anonymous
71 array which is the value corresponding to key "lists":
72
73 @intersection = get_intersection( {
74 lists => [ \@Llist, \@Rlist ],
75 } );
76
77 • Get those items which appear at least once in either list (their
78 union).
79
80 @union = get_union( [ \@Llist, \@Rlist ] );
81
82 or
83
84 @union = get_union( { lists => [ \@Llist, \@Rlist ] } );
85
86 • Get those items which appear (at least once) only in the first
87 list.
88
89 @Lonly = get_unique( [ \@Llist, \@Rlist ] );
90
91 or
92
93 @Lonly = get_unique( { lists => [ \@Llist, \@Rlist ] } );
94
95 • Get those items which appear (at least once) only in the second
96 list.
97
98 @Ronly = get_complement( [ \@Llist, \@Rlist ] );
99
100 or
101
102 @Ronly = get_complement( { lists => [ \@Llist, \@Rlist ] } );
103
104 •
105
106
107 @LorRonly = get_symmetric_difference( [ \@Llist, \@Rlist ] );
108
109 @LorRonly = get_symdiff( [ \@Llist, \@Rlist ] ); # alias
110
111 or
112
113 @LorRonly = get_symmetric_difference( { lists => [ \@Llist, \@Rlist ] } );
114
115 • Make a bag of all those items in both lists. The bag differs from
116 the union of the two lists in that it holds as many copies of
117 individual elements as appear in the original lists.
118
119 @bag = get_bag( [ \@Llist, \@Rlist ] );
120
121 or
122
123 @bag = get_bag( { lists => [ \@Llist, \@Rlist ] } );
124
125 • An alternative approach to the above functions: If you do not
126 immediately require an array as the return value of the function
127 call, but simply need a reference to an (anonymous) array, use one
128 of the following parallel functions:
129
130 $intersection_ref = get_intersection_ref( [ \@Llist, \@Rlist ] );
131 $union_ref = get_union_ref( [ \@Llist, \@Rlist ] );
132 $Lonly_ref = get_unique_ref( [ \@Llist, \@Rlist ] );
133 $Ronly_ref = get_complement_ref( [ \@Llist, \@Rlist ] );
134 $LorRonly_ref = get_symmetric_difference_ref( [ \@Llist, \@Rlist ] );
135 $LorRonly_ref = get_symdiff_ref( [ \@Llist, \@Rlist ] );
136 # alias
137 $bag_ref = get_bag_ref( [ \@Llist, \@Rlist ] );
138
139 or
140
141 $intersection_ref =
142 get_intersection_ref( { lists => [ \@Llist, \@Rlist ] } );
143 $union_ref =
144 get_union_ref( { lists => [ \@Llist, \@Rlist ] } );
145 $Lonly_ref =
146 get_unique_ref( { lists => [ \@Llist, \@Rlist ] } );
147 $Ronly_ref =
148 get_complement_ref( { lists => [ \@Llist, \@Rlist ] } );
149 $LorRonly_ref =
150 get_symmetric_difference_ref( { lists => [ \@Llist, \@Rlist ] } );
151 $LorRonly_ref =
152 get_symdiff_ref( { lists => [ \@Llist, \@Rlist ] } );
153 # alias
154 $bag_ref =
155 get_bag_ref( { lists => [ \@Llist, \@Rlist ] } );
156
157 • Return a true value if the first list ('L' for 'left') is a subset
158 of the second list ('R' for 'right').
159
160 $LR = is_LsubsetR( [ \@Llist, \@Rlist ] );
161
162 or
163
164 $LR = is_LsubsetR( { lists => [ \@Llist, \@Rlist ] } );
165
166 • Return a true value if R is a subset of L.
167
168 $RL = is_RsubsetL( [ \@Llist, \@Rlist ] );
169
170 or
171
172 $RL = is_RsubsetL( { lists => [ \@Llist, \@Rlist ] } );
173
174 • Return a true value if L and R are equivalent, i.e., if every
175 element in L appears at least once in R and vice versa.
176
177 $eqv = is_LequivalentR( [ \@Llist, \@Rlist ] );
178 $eqv = is_LeqvlntR( [ \@Llist, \@Rlist ] ); # alias
179
180 or
181
182 $eqv = is_LequivalentR( { lists => [ \@Llist, \@Rlist ] } );
183
184 • Return a true value if L and R are disjoint, i.e., if L and R have
185 no common elements.
186
187 $disj = is_LdisjointR( [ \@Llist, \@Rlist ] );
188
189 or
190
191 $disj = is_LdisjointR( { lists => [ \@Llist, \@Rlist ] } );
192
193 • Pretty-print a chart showing whether one list is a subset of the
194 other.
195
196 print_subset_chart( [ \@Llist, \@Rlist ] );
197
198 or
199
200 print_subset_chart( { lists => [ \@Llist, \@Rlist ] } );
201
202 • Pretty-print a chart showing whether the two lists are equivalent
203 (same elements found at least once in both).
204
205 print_equivalence_chart( [ \@Llist, \@Rlist ] );
206
207 or
208
209 print_equivalence_chart( { lists => [ \@Llist, \@Rlist ] } );
210
211 • Determine in which (if any) of the lists a given string can be
212 found. In list context, return a list of those indices in the
213 argument list corresponding to lists holding the string being
214 tested.
215
216 @memb_arr = is_member_which( [ \@Llist, \@Rlist ] , [ 'abel' ] );
217
218 or
219
220 @memb_arr = is_member_which( {
221 lists => [ \@Llist, \@Rlist ], # value is array reference
222 item => 'abel', # value is string
223 } );
224
225 In the example above, @memb_arr will be:
226
227 ( 0 )
228
229 because 'abel' is found only in @Al which holds position 0 in the
230 list of arguments passed to "new()".
231
232 • As with other List::Compare::Functional functions which return a
233 list, you may wish the above function returned a (scalar) reference
234 to an array holding the list:
235
236 $memb_arr_ref = is_member_which_ref( [ \@Llist, \@Rlist ] , [ 'baker' ] );
237
238 or
239
240 $memb_arr_ref = is_member_which_ref( {
241 lists => [ \@Llist, \@Rlist ], # value is array reference
242 item => 'baker', # value is string
243 } );
244
245 In the example above, $memb_arr_ref will be:
246
247 [ 0, 1 ]
248
249 because 'baker' is found in @Llist and @Rlist, which hold positions
250 0 and 1, respectively, in the list of arguments passed to "new()".
251
252 Note: functions "is_member_which()" and "is_member_which_ref" test
253 only one string at a time and hence take only one argument. To
254 test more than one string at a time see the next function,
255 "are_members_which()".
256
257 • Determine in "which" (if any) of the lists passed as arguments one
258 or more given strings can be found. The lists beings searched are
259 placed in an array, a reference to which is the first argument
260 passed to "are_members_which()". The strings to be tested are also
261 placed in an array, a reference to which is the second argument
262 passed to that function.
263
264 $memb_hash_ref =
265 are_members_which( [ \@Llist, \@Rlist ] ,
266 [ qw| abel baker fargo hilton zebra | ]
267 );
268
269 or
270
271 $memb_hash_ref = are_members_which( {
272 lists => [ \@Llist, \@Rlist ], # value is arrayref
273 items => [ qw| abel baker fargo hilton zebra | ], # value is arrayref
274 } );
275
276 The return value is a reference to a hash of arrays. The key for
277 each element in this hash is the string being tested. Each
278 element's value is a reference to an anonymous array whose elements
279 are those indices in the constructor's argument list corresponding
280 to lists holding the strings being tested. In the examples above,
281 $memb_hash_ref will be:
282
283 {
284 abel => [ 0 ],
285 baker => [ 0, 1 ],
286 fargo => [ 0, 1 ],
287 hilton => [ 1 ],
288 zebra => [ ],
289 };
290
291 Note: "are_members_which()" can take more than one argument;
292 "is_member_which()" and "is_member_which_ref()" each take only one
293 argument. Unlike those functions, "are_members_which()" returns a
294 hash reference.
295
296 • Determine whether a given string can be found in any of the lists
297 passed as arguments. Return 1 if a specified string can be found
298 in any of the lists and 0 if not.
299
300 $found = is_member_any( [ \@Llist, \@Rlist ] , [ 'abel' ] );
301
302 or
303
304 $found = is_member_any( {
305 lists => [ \@Llist, \@Rlist ], # value is array reference
306 item => 'abel', # value is string
307 } );
308
309 In the example above, $found will be 1 because 'abel' is found in
310 one or more of the lists passed as arguments to "new()".
311
312 • Determine whether a specified string or strings can be found in any
313 of the lists passed as arguments. The lists beings searched are
314 placed in an array, a reference to which is the first argument
315 passed to "are_members_any()". The strings to be tested are also
316 placed in an array, a reference to which is the second argument
317 passed to that function.
318
319 $memb_hash_ref =
320 are_members_any( [ \@Llist, \@Rlist ] ,
321 [ qw| abel baker fargo hilton zebra | ]
322 );
323
324 or
325
326 $memb_hash_ref = are_members_any( {
327 lists => [ \@Llist, \@Rlist ], # value is arrayref
328 items => [ qw| abel baker fargo hilton zebra | ], # value is arrayref
329 } );
330
331 The return value is a reference to a hash where an element's key is
332 the string being tested and the element's value is 1 if the string
333 can be found in any of the lists and 0 if not. In the examples
334 above, $memb_hash_ref will be:
335
336 {
337 abel => 1,
338 baker => 1,
339 fargo => 1,
340 hilton => 1,
341 zebra => 0,
342 };
343
344 "zebra"'s value is 0 because "zebra" is not found in either of the
345 lists passed as arguments to "are_members_any()".
346
347 • Return current List::Compare::Functional version number.
348
349 $vers = get_version;
350
351 Comparing Three or More Lists Held in Arrays
352 Given five lists:
353
354 @Al = qw(abel abel baker camera delta edward fargo golfer);
355 @Bob = qw(baker camera delta delta edward fargo golfer hilton);
356 @Carmen = qw(fargo golfer hilton icon icon jerky kappa);
357 @Don = qw(fargo icon jerky);
358 @Ed = qw(fargo icon icon jerky);
359
360 • Get those items which appear at least once in each list (their
361 intersection).
362
363 @intersection = get_intersection( [ \@Al, \@Bob, \@Carmen, \@Don, \@Ed ] );
364
365 or
366
367 @intersection = get_intersection( {
368 lists => [ \@Al, \@Bob, \@Carmen, \@Don, \@Ed ],
369 } );
370
371 • Get those items which appear at least once in any of the lists
372 (their union).
373
374 @union = get_union( [ \@Al, \@Bob, \@Carmen, \@Don, \@Ed ] );
375
376 or
377 @union = get_union( {
378 lists => [ \@Al, \@Bob, \@Carmen, \@Don, \@Ed ],
379 } );
380
381 • To get those items which are unique to a particular list, provide
382 "get_unique()" with two array references. The first holds
383 references to the arrays which in turn hold the individual lists
384 being compared. The second holds the index position in the first
385 reference of the particular list under consideration. Example: To
386 get elements unique to @Carmen:
387
388 @Lonly = get_unique(
389 [ \@Al, \@Bob, \@Carmen, \@Don, \@Ed ],
390 [ 2 ]
391 );
392
393 or
394
395 @Lonly = get_unique( {
396 lists => [ \@Al, \@Bob, \@Carmen, \@Don, \@Ed ], # value is arrayref
397 item => 2, # value is number
398 } );
399
400 If no index position is passed to "get_unique()" it will default to
401 0 and report items unique to the first list passed to the function.
402 Hence,
403
404 @Lonly = get_unique( [ \@Al, \@Bob, \@Carmen, \@Don, \@Ed ] );
405
406 is same as:
407
408 @Lonly = get_unique( [ \@Al, \@Bob, \@Carmen, \@Don, \@Ed ], [ 0 ] );
409
410 • Should you need to identify the items unique to each of the lists
411 under consideration, call "get_unique_all" and get a reference to
412 an array of array references:
413
414 $unique_all_ref = get_unique_all(
415 [ \@Al, \@Bob, \@Carmen, \@Don, \@Ed ]
416 );
417
418 or
419
420 $unique_all_ref = get_unique_all( {
421 lists => [ \@Al, \@Bob, \@Carmen, \@Don, \@Ed ],
422 } );
423
424 • To get those items which appear only in lists other than one
425 particular list, pass two array references to the
426 "get_complement()" function. The first holds references to the
427 arrays which in turn hold the individual lists being compared. The
428 second holds the index position in the first reference of the
429 particular list under consideration. Example: to get all the
430 elements found in lists other than @Don:
431
432 @Ronly = get_complement(
433 [ \@Al, \@Bob, \@Carmen, \@Don, \@Ed ],
434 [ 3 ]
435 );
436
437 or
438
439 @Ronly = get_complement( {
440 lists => [ \@Al, \@Bob, \@Carmen, \@Don, \@Ed ], # value is arrayref
441 item => 3, # value is number
442 } );
443
444 If no index position is passed to "get_complement()" it will
445 default to 0 and report items found in all lists other than the
446 first list passed to "get_complement()".
447
448 @Lonly = get_complement( [ \@Al, \@Bob, \@Carmen, \@Don, \@Ed ] );
449
450 is same as:
451
452 @Lonly = get_complement( [ \@Al, \@Bob, \@Carmen, \@Don, \@Ed ], [ 0 ] );
453
454 • Should you need to identify the items not found in each of the
455 lists under consideration, call "get_complement_all" and get a
456 reference to an array of array references:
457
458 $complement_all_ref = get_complement_all(
459 [ \@Al, \@Bob, \@Carmen, \@Don, \@Ed ]
460 );
461
462 or
463
464 $complement_all_ref = get_complement_all( {
465 lists => [ \@Al, \@Bob, \@Carmen, \@Don, \@Ed ],
466 } );
467
468 • Get those items which do not appear in more than one of several
469 lists (their symmetric_difference);
470
471 @LorRonly = get_symmetric_difference( [ \@Al, \@Bob, \@Carmen, \@Don, \@Ed ] );
472 @LorRonly = get_symdiff( [ \@Al, \@Bob, \@Carmen, \@Don, \@Ed ] ); # alias
473
474 or
475
476 @LorRonly = get_symmetric_difference( {
477 lists => [ \@Al, \@Bob, \@Carmen, \@Don, \@Ed ],
478 } );
479
480 • Get those items found in any of several lists which do not appear
481 in "all" of the lists (i.e., all items except those found in the
482 intersection of the lists):
483
484 @nonintersection = get_nonintersection(
485 [ \@Al, \@Bob, \@Carmen, \@Don, \@Ed ] );
486
487 or
488
489 @nonintersection = get_nonintersection( {
490 lists => [ \@Al, \@Bob, \@Carmen, \@Don, \@Ed ],
491 } );
492
493 • Get those items which appear in more than one of several lists
494 (i.e., all items except those found in their symmetric difference);
495
496 @shared = get_shared( [ \@Al, \@Bob, \@Carmen, \@Don, \@Ed ] );
497
498 or
499
500 @shared = get_shared( {
501 lists => [ \@Al, \@Bob, \@Carmen, \@Don, \@Ed ],
502 } );
503
504 • Make a bag of every item found in every list. The bag differs from
505 the union of the two lists in that it holds as many copies of
506 individual elements as appear in the original lists.
507
508 @bag = get_bag( [ \@Al, \@Bob, \@Carmen, \@Don, \@Ed ] );
509
510 or
511
512 @bag = get_bag( {
513 lists => [ \@Al, \@Bob, \@Carmen, \@Don, \@Ed ],
514 } );
515
516 • An alternative approach to the above functions: If you do not
517 immediately require an array as the return value of the function,
518 but simply need a reference to an array, use one of the following
519 parallel functions:
520
521 $intersection_ref = get_intersection_ref(
522 [ \@Al, \@Bob, \@Carmen, \@Don, \@Ed ] );
523 $union_ref = get_union_ref(
524 [ \@Al, \@Bob, \@Carmen, \@Don, \@Ed ] );
525 $Lonly_ref = get_unique_ref(
526 [ \@Al, \@Bob, \@Carmen, \@Don, \@Ed ] );
527 $Ronly_ref = get_complement_ref(
528 [ \@Al, \@Bob, \@Carmen, \@Don, \@Ed ] );
529 $LorRonly_ref = get_symmetric_difference_ref(
530 [ \@Al, \@Bob, \@Carmen, \@Don, \@Ed ] );
531 $LorRonly_ref = get_symdiff_ref( # alias
532 [ \@Al, \@Bob, \@Carmen, \@Don, \@Ed ] );
533 $nonintersection_ref = get_nonintersection_ref(
534 [ \@Al, \@Bob, \@Carmen, \@Don, \@Ed ] );
535 $shared_ref = get_shared_ref(
536 [ \@Al, \@Bob, \@Carmen, \@Don, \@Ed ] );
537 $bag_ref = get_bag_ref(
538 [ \@Al, \@Bob, \@Carmen, \@Don, \@Ed ] );
539
540 • To determine whether one particular list is a subset of another of
541 the lists passed to the function, pass to "is_LsubsetR()" two array
542 references. The first of these is a reference to an array of array
543 references, the arrays holding the lists under consideration. The
544 second is a reference to a two-element array consisting of the
545 index of the presumed subset, followed by the index position of the
546 presumed superset. A true value (1) is returned if the first
547 (left-hand) element in the second reference list is a subset of the
548 second (right-hand) element; a false value (0) is returned
549 otherwise.
550
551 Example: To determine whether @Ed is a subset of @Carmen, call:
552
553 $LR = is_LsubsetR(
554 [ \@Al, \@Bob, \@Carmen, \@Don, \@Ed ],
555 [ 4, 2 ]
556 );
557
558 or
559
560 $LR = is_LsubsetR( {
561 lists => [ \@Al, \@Bob, \@Carmen, \@Don, \@Ed ], # value is arrayref
562 pair => [ 4, 2 ], # value is arrayref
563 } );
564
565 If only the first reference (to the array of lists) is passed to
566 "is_LsubsetR", then the function's second argument defaults to
567 "(0,1)" and compares the first two lists passed to the constructor.
568 So,
569
570 $LR = is_LsubsetR([ \@Al, \@Bob, \@Carmen, \@Don, \@Ed ] );
571
572 ... is equivalent to:
573
574 $LR = is_LsubsetR([ \@Al, \@Bob, \@Carmen, \@Don, \@Ed ], [0,1] );
575
576 • To reverse the order in which the particular lists are evaluated
577 for superset/subset status, call "is_RsubsetL":
578
579 $RL = is_RsubsetL([ \@Al, \@Bob, \@Carmen, \@Don, \@Ed ], [2,4] );
580
581 or
582
583 $RL = is_RsubsetL( {
584 lists => [ \@Al, \@Bob, \@Carmen, \@Don, \@Ed ],
585 pair => [ 2, 4 ],
586 } );
587
588 • List::Compare::Functional considers two lists to be equivalent if
589 every element in one list appears at least once in R and vice
590 versa. To determine whether one particular list passed to the
591 function is equivalent to another of the lists passed to the
592 function, provide "is_LequivalentR()" with two array references.
593 The first is a reference to an array of array references, the
594 arrays holding the lists under consideration. The second of these
595 is a reference to a two-element array consisting of the two lists
596 being tested for equivalence. A true value (1) is returned if the
597 lists are equivalent; a false value (0) is returned otherwise.
598
599 Example: To determine whether @Don and @Ed are equivalent, call:
600
601 $eqv = is_LequivalentR(
602 [ \@Al, \@Bob, \@Carmen, \@Don, \@Ed ],
603 [3,4]
604 );
605
606 $eqv = is_LeqvlntR( # alias
607 [ \@Al, \@Bob, \@Carmen, \@Don, \@Ed ],
608 [3,4]
609 );
610
611 or
612
613 $eqv = is_LequivalentR( {
614 items => [ \@Al, \@Bob, \@Carmen, \@Don, \@Ed ],
615 pair => [3,4],
616 } );
617
618 If no arguments are passed, "is_LequivalentR" defaults to "[0,1]"
619 and compares the first two lists passed to the function. So,
620
621 $eqv = is_LequivalentR( [ \@Al, \@Bob, \@Carmen, \@Don, \@Ed ] );
622
623 ... translates to:
624
625 $eqv = is_LequivalentR( [ \@Al, \@Bob, \@Carmen, \@Don, \@Ed ], [0,1] );
626
627 • To determine whether any two of the lists passed to the function
628 are disjoint from one another (i.e., have no common members),
629 provide "is_LdisjointR()" with two array references. The first is
630 a reference to an array of array references, the arrays holding the
631 lists under consideration. The second of these is a reference to a
632 two-element array consisting of the two lists being tested for
633 disjointedness. A true value (1) is returned if the lists are
634 disjoint; a false value (0) is returned otherwise.
635
636 Example: To determine whether @Don and @Ed are disjoint, call:
637
638 $disj = is_LdisjointR(
639 [ \@Al, \@Bob, \@Carmen, \@Don, \@Ed ],
640 [3,4]
641 );
642
643 or
644
645 $disj = is_LdisjointR( {
646 items => [ \@Al, \@Bob, \@Carmen, \@Don, \@Ed ],
647 pair => [3,4]
648 } );
649
650 • Pretty-print a chart showing the subset relationships among the
651 various source lists:
652
653 print_subset_chart( [ \@Al, \@Bob, \@Carmen, \@Don, \@Ed ] );
654
655 or
656
657 print_subset_chart( { lists => [ \@Al, \@Bob, \@Carmen, \@Don, \@Ed ] } );
658
659 • Pretty-print a chart showing the equivalence relationships among
660 the various source lists:
661
662 print_equivalence_chart( [ \@Al, \@Bob, \@Carmen, \@Don, \@Ed ] );
663
664 or
665
666 print_equivalence_chart( { lists => [ \@Al, \@Bob, \@Carmen, \@Don, \@Ed ] } );
667
668 • Determine in which (if any) of several lists a given string can be
669 found. Pass two array references, the first of which holds
670 references to arrays holding the lists under consideration, and the
671 second of which holds a single-item list consisting of the string
672 being tested.
673
674 @memb_arr = is_member_which(
675 [ \@Al, \@Bob, \@Carmen, \@Don, \@Ed ],
676 [ 'abel' ]
677 );
678
679 or
680
681 @memb_arr = is_member_which( {
682 lists => [ \@Al, \@Bob, \@Carmen, \@Don, \@Ed ], # value is arrayref
683 item => 'abel', # value is string
684 } );
685
686 In list context, return a list of those indices in the function's
687 argument list corresponding to lists holding the string being
688 tested. In the example above, @memb_arr will be:
689
690 ( 0 )
691
692 because 'abel' is found only in @Al which holds position 0 in the
693 list of arguments passed to "is_member_which()".
694
695 • As with other List::Compare::Functional functions which return a
696 list, you may wish the above function returned a reference to an
697 array holding the list:
698
699 $memb_arr_ref = is_member_which_ref(
700 [ \@Al, \@Bob, \@Carmen, \@Don, \@Ed ],
701 [ 'jerky' ]
702 );
703
704 or
705
706 $memb_arr_ref = is_member_which_ref( {
707 lists => [ \@Al, \@Bob, \@Carmen, \@Don, \@Ed ], # value is arrayref
708 item => 'jerky', # value is string
709 } );
710
711 In the example above, $memb_arr_ref will be:
712
713 [ 3, 4 ]
714
715 because 'jerky' is found in @Don and @Ed, which hold positions 3
716 and 4, respectively, in the list of arguments passed to
717 "is_member_which()".
718
719 Note: functions "is_member_which()" and "is_member_which_ref" test
720 only one string at a time and hence take only one element in the
721 second array reference argument. To test more than one string at a
722 time see the next function, "are_members_which()".
723
724 • Determine in "which" (if any) of several lists one or more given
725 strings can be found. Pass two array references, the first of
726 which holds references to arrays holding the lists under
727 consideration, and the second of which holds a list of the strings
728 being tested.
729
730 $memb_hash_ref = are_members_which(
731 [ \@Al, \@Bob, \@Carmen, \@Don, \@Ed ],
732 [ qw| abel baker fargo hilton zebra | ]
733 );
734
735 or
736
737 $memb_hash_ref = are_members_which( {
738 lists => [ \@Al, \@Bob, \@Carmen, \@Don, \@Ed ], # value is arrayref
739 items => [ qw| abel baker fargo hilton zebra | ], # value is arrayref
740 } );
741
742 The return valus is a reference to a hash of arrays. In this hash,
743 each element's value is a reference to an anonymous array whose
744 elements are those indices in the argument list corresponding to
745 lists holding the strings being tested. In the two examples above,
746 $memb_hash_ref will be:
747
748 {
749 abel => [ 0 ],
750 baker => [ 0, 1 ],
751 fargo => [ 0, 1, 2, 3, 4 ],
752 hilton => [ 1, 2 ],
753 zebra => [ ],
754 };
755
756 Note: "are_members_which()" tests more than one string at a time.
757 Hence, its second array reference argument can take more than one
758 element. "is_member_which()" and "is_member_which_ref()" each take
759 only one element in their second array reference arguments.
760 "are_members_which()" returns a hash reference; the other functions
761 return either a list or a reference to an array holding that list,
762 depending on context.
763
764 • Determine whether a given string can be found in any of several
765 lists. Pass two array references, the first of which holds
766 references to arrays holding the lists under consideration, and the
767 second of which holds a single-item list of the string being
768 tested.
769
770 $found = is_member_any(
771 [ \@Al, \@Bob, \@Carmen, \@Don, \@Ed ],
772 [ 'abel' ]
773 );
774
775 or
776
777 $found = is_member_any( {
778 lists => [ \@Al, \@Bob, \@Carmen, \@Don, \@Ed ], # value is arrayref
779 item => 'abel', # value is string
780 } );
781
782 The return value is 1 if a specified string can be found in any of
783 the lists and 0 if not. In the example above, $found will be 1
784 because "abel" is found in one or more of the lists passed as
785 arguments to "is_member_any()".
786
787 • Determine whether a specified string or strings can be found in any
788 of several lists. Pass two array references, the first of which
789 holds references to arrays holding the lists under consideration,
790 and the second of which holds a list of the strings being tested.
791
792 $memb_hash_ref = are_members_any(
793 [ \@Al, \@Bob, \@Carmen, \@Don, \@Ed ],
794 [ qw| abel baker fargo hilton zebra | ]
795 );
796
797 or
798
799 $memb_hash_ref = are_members_any( {
800 lists => [ \@Al, \@Bob, \@Carmen, \@Don, \@Ed ], # value is arrayref
801 items => [ qw| abel baker fargo hilton zebra | ], # value is arrayref
802 } );
803
804 The return value is a reference to a hash where an element's key is
805 the string being tested and the element's value is 1 if the string
806 can be found in any of the lists and 0 if not. In the example
807 above, $memb_hash_ref will be:
808
809 {
810 abel => 1,
811 baker => 1,
812 fargo => 1,
813 hilton => 1,
814 zebra => 0,
815 };
816
817 "zebra"'s value is 0 because "zebra" is not found in any of the
818 lists passed as arguments to "are_members_any()".
819
820 • Return current List::Compare::Functional version number:
821
822 $vers = get_version;
823
824 Comparing Lists Held in Seen-Hashes
825 What is a seen-hash? A seen-hash is a typical Perl implementation of a
826 look-up table: a hash where the value for a given element represents
827 the number of times the element's key is observed in a list. For the
828 purposes of List::Compare::Functional, what is crucial is whether an
829 item is observed in a list or not; how many times the item occurs in a
830 list is, with one exception, irrelevant. (That exception is the
831 "get_bag()" function and its fraternal twin "get_bag_ref()". In this
832 case only, the key in each element of the seen-hash is placed in the
833 bag the number of times indicated by the value of that element.) The
834 value of an element in a List::Compare seen-hash must be a positive
835 integer, but whether that integer is 1 or 1,000,001 is immaterial for
836 all List::Compare::Functional functions except forming a bag.
837
838 The two lists compared above were represented by arrays; references to
839 those arrays were passed to the various List::Compare::Functional
840 functions. They could, however, have been represented by seen-hashes
841 such as the following and passed in exactly the same manner to the
842 various functions.
843
844 %Llist = (
845 abel => 2,
846 baker => 1,
847 camera => 1,
848 delta => 1,
849 edward => 1,
850 fargo => 1,
851 golfer => 1,
852 );
853 %Rlist = (
854 baker => 1,
855 camera => 1,
856 delta => 2,
857 edward => 1,
858 fargo => 1,
859 golfer => 1,
860 hilton => 1,
861 );
862
863 @intersection = get_intersection( [ \%Llist, \%Rlist ] );
864 @union = get_union( [ \%Llist, \%Rlist ] );
865 @complement = get_complement( [ \%Llist, \%Rlist ] );
866
867 and so forth.
868
869 To compare three or more lists simultaneously, provide the appropriate
870 List::Compare::Functional function with a first array reference holding
871 a list of three or more references to seen-hashes. Thus,
872
873 @union = get_intersection( [ \%Alpha, \%Beta, \%Gamma ] );
874
875 The 'single hashref' format for List::Compare::Functional functions is
876 also available when passing seen-hashes as arguments. Examples:
877
878 @intersection = get_intersection( {
879 lists => [ \%Alpha, \%Beta, \%Gamma ],
880 } );
881
882 @Ronly = get_complement( {
883 lists => [ \%Alpha, \%Beta, \%Gamma ],
884 item => 3,
885 } );
886
887 $LR = is_LsubsetR( {
888 lists => [ \%Alpha, \%Beta, \%Gamma ],
889 pair => [ 4, 2 ],
890 } );
891
892 $memb_hash_ref = are_members_any( {
893 lists => [ \%Alpha, \%Beta, \%Gamma ],
894 items => [ qw| abel baker fargo hilton zebra | ],
895 } );
896
897 Faster Results with the Unsorted Option
898 By default, List::Compare::Function functions return lists sorted in
899 Perl's default ASCII-betical mode. Sorting entails a performance cost,
900 and if you do not need a sorted list and do not wish to pay this
901 performance cost, you may call the following List::Compare::Function
902 functions with the 'unsorted' option:
903
904 @intersection = get_intersection( '-u', [ \@Llist, \@Rlist ] );
905 @union = get_union( '-u', [ \@Llist, \@Rlist ] );
906 @Lonly = get_unique( '-u', [ \@Llist, \@Rlist ] );
907 @Ronly = get_complement( '-u', [ \@Llist, \@Rlist ] );
908 @LorRonly = get_symmetric_difference('-u', [ \@Llist, \@Rlist ] );
909 @bag = get_bag( '-u', [ \@Llist, \@Rlist ] );
910
911 For greater readability, the option may be spelled out:
912
913 @intersection = get_intersection('--unsorted', [ \@Llist, \@Rlist ] );
914
915 or
916
917 @intersection = get_intersection( {
918 unsorted => 1,
919 lists => [ \@Llist, \@Rlist ],
920 } );
921
922 Should you need a reference to an unsorted list as the return value,
923 you may call the unsorted option as follows:
924
925 $intersection_ref = get_intersection_ref(
926 '-u', [ \@Llist, \@Rlist ] );
927 $intersection_ref = get_intersection_ref(
928 '--unsorted', [ \@Llist, \@Rlist ] );
929
931 General Comments
932 List::Compare::Functional is a non-object-oriented implementation of
933 very common Perl code used to determine interesting relationships
934 between two or more lists at a time. List::Compare::Functional is
935 based on the same author's List::Compare module found in the same CPAN
936 distribution. List::Compare::Functional is closely modeled on the
937 ''Accelerated'' mode in List::Compare.
938
939 For a discussion of the antecedents of this module, see the discussion
940 of the history and development of this module in the documentation to
941 List::Compare.
942
943 List::Compare::Functional's Export Tag Groups
944 By default, List::Compare::Functional exports no functions. You may
945 import individual functions into your main package but may find it more
946 convenient to import via export tag groups. Four such groups are
947 currently defined:
948
949 use List::Compare::Functional qw(:main)
950 use List::Compare::Functional qw(:mainrefs)
951 use List::Compare::Functional qw(:originals)
952 use List::Compare::Functional qw(:aliases)
953
954 • Tag group ":main" includes what, in the author's opinion, are the
955 six List::Compare::Functional subroutines mostly likely to be used:
956
957 get_intersection()
958 get_union()
959 get_unique()
960 get_complement()
961 get_symmetric_difference()
962 is_LsubsetR()
963
964 • Tag group ":mainrefs" includes five of the six subroutines found in
965 ":main" -- all except "is_LsubsetR()" -- in the form in which they
966 return references to arrays rather than arrays proper:
967
968 get_intersection_ref()
969 get_union_ref()
970 get_unique_ref()
971 get_complement_ref()
972 get_symmetric_difference_ref()
973
974 • Tag group ":originals" includes all List::Compare::Functional
975 subroutines in their 'original' form, i.e., no aliases for those
976 subroutines:
977
978 get_intersection
979 get_intersection_ref
980 get_union
981 get_union_ref
982 get_unique
983 get_unique_ref
984 get_unique_all
985 get_complement
986 get_complement_ref
987 get_complement_all
988 get_symmetric_difference
989 get_symmetric_difference_ref
990 get_shared
991 get_shared_ref
992 get_nonintersection
993 get_nonintersection_ref
994 is_LsubsetR
995 is_RsubsetL
996 is_LequivalentR
997 is_LdisjointR
998 is_member_which
999 is_member_which_ref
1000 are_members_which
1001 is_member_any
1002 are_members_any
1003 print_subset_chart
1004 print_equivalence_chart
1005 get_bag
1006 get_bag_ref
1007
1008 • Tag group ":aliases" contains all List::Compare::Functional
1009 subroutines which are aliases for subroutines found in tag group
1010 ":originals". These are provided simply for less typing.
1011
1012 get_symdiff
1013 get_symdiff_ref
1014 is_LeqvlntR
1015
1016 April 2004 Change of Interface
1017 Note: You can skip this section unless you used
1018 List::Compare::Functional prior to the release of Version 0.25 in April
1019 2004.
1020
1021 Version 0.25 initiated a significant change in the interface to this
1022 module's various functions. In order to be able to accommodate
1023 comparisons among more than two lists, it was necessary to change the
1024 type of arguments passed to the various functions. Whereas previously
1025 a typical List::Compare::Functional function would be called like this:
1026
1027 @intersection = get_intersection( \@Llist, \@Rlist ); # SUPERSEDED
1028
1029 ... now the references to the lists being compared must now be placed
1030 within a wrapper array (anonymous or named), a reference to which is
1031 now passed to the function, like so:
1032
1033 @intersection = get_intersection( [ \@Llist, \@Rlist ] );
1034
1035 ... or, alternatively:
1036
1037 @to_be_compared = (\@Llist, \@Rlist);
1038 @intersection = get_intersection( \@to_be_compared );
1039
1040 In a similar manner, List::Compare::Functional functions could
1041 previously take arguments in the form of references to 'seen-hashes'
1042 instead of references to arrays:
1043
1044 @intersection = get_intersection( \%h0, \%h1 );
1045
1046 (See above for discussion of seen-hashes.) Now, those references to
1047 seen-hashes must be placed within a wrapper array (anonymous or named),
1048 a reference to which is passed to the function, like so:
1049
1050 @intersection = get_intersection( [ \%h0, \%h1 ] );
1051
1052 Also, in a similar manner, some List::Compare::Functional functions
1053 previously took arguments in addition to the lists being compared.
1054 These arguments were simply passed as scalars, like this:
1055
1056 @memb_arr = is_member_which(\@Llist, \@Rlist, 'abel');
1057
1058 Now these arguments must also be placed within a wrapper array
1059 (anonymous or named), a reference to which is now passed to the
1060 function, like so:
1061
1062 @memb_arr = is_member_which( [ \@Llist, \@Rlist ], [ 'abel' ] );
1063
1064 ... or, alternatively:
1065
1066 @to_be_compared = (\@Llist, \@Rlist);
1067 @opts = ( 'abel' );
1068 @memb_arr = is_member_which( \@to_be_compared, \@opts );
1069
1070 As in previous versions, for a speed boost the user may provide the
1071 '-u' or '--unsorted' option as the first argument to some
1072 List::Compare::Functional functions. Using this option, the
1073 "get_intersection()" function above would appear as:
1074
1075 @intersection = get_intersection( '-u', [ \@Llist, \@Rlist ] );
1076
1077 ... or, alternatively:
1078
1079 @intersection = get_intersection( '--unsorted', [ \@Llist, \@Rlist ] );
1080
1081 The arguments to any List::Compare::Functional function will therefore
1082 consist possibly of the unsorted option, and then of either one or two
1083 references to arrays, the first of which is a reference to an array of
1084 arrays or an array of seen-hashes.
1085
1087 James E. Keenan (jkeenan@cpan.org). When sending correspondence,
1088 please include 'List::Compare::Functional' or 'List-Compare-Functional'
1089 in your subject line.
1090
1091 Creation date: May 20, 2002. Last modification date: August 16 2020.
1092 Copyright (c) 2002-20 James E. Keenan. United States. All rights
1093 reserved. This is free software and may be distributed under the same
1094 terms as Perl itself.
1095
1096
1097
1098perl v5.32.1 2021-01-27 List::Compare::Functional(3)