in reply to Re: remove element from 2D array after comparing it with other 2D array
in thread remove element from 2D array after comparing it with other 2D array

Hi again Haukex. What i need to do is to make sure that my @array1 sequence is the same with @array2.

For example if my input is this:

my @array1 = ('ux_prim_clk', 'ux_side_clk', 'ux_xtal_frm_refclk');

my @array2 = ('ccu_ux_xtal_frm_refclk_ack', 'ibbs_ux_prim_clkack','sbr_ux_side_clkack');

And, after doing the comparison, my output is:

@array1 = ('ux_xtal_frm_refclk', 'ux_prim_clk', 'ux_side_clk')

@array2 = ('ccu_ux_xtal_frm_refclk_ack', 'ibbs_ux_prim_clkack','sbr_ux_side_clkack')

I want to use @array2 as reference and make sure that @array1 is following the same sequence as @array2. Note that i cannot simply use name to compare because the name of element inside @array1 & @array2 can be changed.

Let say from @array1, the first row's element is ('ux_prim_clk') and for the @array2, the first row's element is ('ccu_ux_xtal_frm_refclk_ack'). Now, i want to compare these two but i want to compare it word by word (Eg: ux & ccu, prim & ux, clk & xtal).

But the constraint now is that my @array2 first row's element has different size with @array1. So that's why i want to splice array2 first row's element and compare it with the first row's element of @array1. My @array1 is maintain throughout the comparison.

For example (using first row's element for both arrays):

@array1 = (ux, prim, clk) @array2 = (ccu, ux, xtal, frm, refclk, ack)

1. compare: ux & ccu, prim & ux, clk & xtal.

2. compare: ux & ux, prim & xtal, clk & frm.

3. compare: ux & xtal, prim & frm, clk & refclk.

4. compare: ux & frm, prim & refclk, clk & ack.

Each time it compares (1 - 4), i want to store the number of match inside let say $match variable, and overwrite it if it has highest number of match. For example:

$highest_match = 0; if ($match > $highest_match){ $highest_match = $match; } $highest_percentage = ($highest_match/no. of element in array1's row)* +100;

I will then plan to do condition if (highest_percentage > 50%), i will store the entire row of @array2 inside another array.

So i will end up with the output that i want inside this new array.

I hope this clears your confusion. I'm sorry i really bad at explaining. I only learn c language before so this language is very new to me. I really appreciate your effort.

  • Comment on Re^2: remove element from 2D array after comparing it with other 2D array
  • Download Code

Replies are listed 'Best First'.
Re^3: remove element from 2D array after comparing it with other 2D array
by haukex (Archbishop) on May 02, 2019 at 11:12 UTC

    Ok, I think I understand your algorithm, it seems very similar to the LCSS idea I mentioned and showed, except you want to split words on underscores, and I think you want to compare each word exactly? (In that case, when comparing sbr_ux_side_clkack with ux_side_clk, the match would only be ux_side.)

    I could implement your algorithm more or less literally, although in the following I haven't implemented the 50% rule you mentioned - it just picks the @array1 element with the best match, and also there is currently no protection against picking the same @array1 element twice. Instead of spliceing the @array2 elements, which is a destructive operation, I use different offsets. However, as you can tell, the whole thing gets kind of complex, plus, because of the four (!) nested loops, if the strings and/or arrays get longer, it will be less and less performant! But maybe this is a good starting point anyway.

    By the way, @array1 and @array2 aren't very descriptive names, I recommend you choose some better (more descriptive) variable names.

    use warnings; use strict; use Data::Dump qw/dd pp/; my @array1 = ('ux_prim_clk', 'ux_side_clk', 'ux_xtal_frm_refclk'); my @array2 = ('ccu_ux_xtal_frm_refclk_ack', 'ibbs_ux_prim_clkack', 'sbr_ux_side_clkack'); my @aoa1 = map { [ split /_/, $_ ] } @array1; my @output; # Using @array2 for the basis of ordering, so loop over that first for my $a2 ( map { [ split /_/, $_ ] } @array2 ) { #print "##### "; dd $a2; # debug # Now look through @array1 for the best match my ($highest_match, $highest_match_at_a1idx) = (-1); for my $i ( 0 .. $#aoa1 ) { # in this loop, keep track of index my $a1 = $aoa1[$i]; # The following code relies on @$a1 >= @$a2, so check that if ( @$a2 < @$a1 ) { warn "Skipping ".pp($a2, $a1); next } # Try matching $a1 against $a2 at different offsets for my $offset ( 0 .. @$a2 - @$a1 ) { my $match = 0; # Count the number of matching elements at each offset for my $j ( 0 .. $#$a1 ) { if ( $a2->[$offset+$j] eq $a1->[$j] ) { $match++ } else { last } # failed to match, stop looking } # If this index and offset matches better, record that if ( $match && $match > $highest_match ) { #dd $a2, $offset, $a1, $match; # debug $highest_match = $match; $highest_match_at_a1idx = $i; } } } if ( defined $highest_match_at_a1idx ) { push @output, $array1[$highest_match_at_a1idx] } else { warn "Failed to find match for ".pp($a2) } } dd @array1; dd @array2; dd @output; __END__ ("ux_prim_clk", "ux_side_clk", "ux_xtal_frm_refclk") ( "ccu_ux_xtal_frm_refclk_ack", "ibbs_ux_prim_clkack", "sbr_ux_side_clkack", ) ("ux_xtal_frm_refclk", "ux_prim_clk", "ux_side_clk")

      Hi Haukex, first of all, thank you so much for your effort.

      I'm sorry but since I'm not very familiar with this language, I find it a bit hard to comprehend this code. May I know what is this part means:

      my ($highest_match, $highest_match_at_a1idx) = (-1);

      You have stated in the code that it will look through @array1 for the best match, but I search the (-1) function in google but they did not gave me information that I can relate with this.

      I also a bit confuse with the function of .pp in your code. Does this store the variable somewhere?

      Really appreciate if you can answer this. Thank you again sir.

        my ($highest_match, $highest_match_at_a1idx) = (-1);

        You might not have spotted it but this is merely list assignment. The list on the right of the equals sign is assigned to the list on the left, so after this assignment, $highest_match has value -1. Since the left list has 2 elements but the right list has only 1, the second element on the left $highest_match_at_a1idx is undef.

        I also a bit confuse with the function of .pp in your code. Does this store the variable somewhere?

        No, it's just a pretty printer. See Data::Dump::pp.