2

I have array @hon_data. If any elements of the array are one of a known list of values, I return zero.

for my $hon_field (@hon_data) {
    if($hon_field ne 'B' and $hon_field ne 'S' and $hon_field ne 'G' and 
      $hon_field ne 'D' and $hon_field ne 'L') {
      return 0;
    }
  } 

The number of values to check is growing, so this approach is getting complicated to manage. Is there a way to do this with the values in an array?

my @results =("B","G","S","D","N","L");
my @results2 = ("A","G","S","D","N","L");

sub uniq {
    my %seen;
    grep { !$seen{$_}++ } @_;
}

my @unique = uniq(@results, @results2);

In result2 A is unique value and it should return A only But this code is not working.

7
  • Are these sets (no repeated values)? If so, then what you want is called symmetric difference Commented Nov 2, 2022 at 13:28
  • @ikegami I have a fixed array let's say array1 and there is an array2 coming from user . If any value which is coming from user is not in array1 we need to report that . Commented Nov 2, 2022 at 13:36
  • I would think using hashes would be a super fast solution instead of arrays. See oreilly.com/library/view/perl-cookbook/1565922433/ch05s12.html Commented Nov 2, 2022 at 13:37
  • Sounds more like a normal set difference, not symmetric difference. Commented Nov 2, 2022 at 16:38
  • @Shawn yes I agree with you not sure why everyone thinks it is symmetric Commented Nov 2, 2022 at 16:52

1 Answer 1

2

You're asking how to replace the hardcoded loop with a dynamic one. The following is one way this could be done:

for my $hon_field ( @hon_data ) {
   for my $ok (qw( B S G D L )) {
      if ( $hon_field ne $ok ) {
         return 0;
      }
   }
}

That is a lot better. But if the elements are strings, the inner loop can be replaced with a hash lookup.

my %ok = map { $_ => 1 } qw( B S G D L );

for my $hon_field ( @hon_data ) {
   if ( !$ok{ $hon_field } ) {
      return 0;
   }
}

This can also be written as follows:

use List::Util qw( any );

my %ok = map { $_ => 1 } qw( B S G D L );

return 0 if any { !$ok{$_} } @hon_data;

A similar approach can be used to find the difference of sets.

my %ok = map { $_ => 1 } qw( B S G D L );;

my @diff = grep { !$ok{ $_ } } @hon_data;    # diff = hon_data - { B, S, G, D, L }
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.