in reply to Re^2: matching pdl elements
in thread matching pdl elements

I'm trying to teach to fish. But I'm not a very good teacher. So here's 99% of a fish.

You need to consider what $a == $b->dummy does (because thats all I gave you). It creates a matrix of equality between $a and $b.

perldl> $a = sequence(5) perldl> $b = pdl [1,4,9,16] perldl> p $c = $a == $b->dummy [ [0 1 0 0 0] [0 0 0 0 1] [0 0 0 0 0] [0 0 0 0 0] ] # This matrix's horizontal dim corresponds to $a # and the vertical to $b. # In other words, $c->($x,$y) is $a->($x) == $b->($y) perldl> p which $c [1 9] # Confusing results? Think about the matrix above. # Can you see a pattern? # I mentioned 'flatten' in an earlier post. That was a clue. perldl>p $c->flat [0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0] # This looks like all the rows of the matrix concatenated. # And look, the values at 1 and 9 are the only true ones
Turns out the indices of values in $c->flat correspond to their position in $c using the equation:
$c_flat_pos = $c_dim_0_pos + $c_dim_1_pos * $sizeof_c_dim_0
And that is related to $a and $b like so:
$c_flat_pos = $index_in_a + ($index_in_b * $sizeof_a)
Note that the term $index_in_a will alway be less than $sizeof_a and that the term ($index_in_b * $sizeof_$a) will alway be a multiple of $sizeof_a. In other words, we're looking for the remainder of which $c when divided by $a->dim(0). This is known as the modulo operation.

Of course, TIMTOWTDI. You can solve this problem in many ways. Another common take is summation (works like logical or) over the dimensions you don't care about. And the decision to put the dummy dim on $b was arbitrary.

Replies are listed 'Best First'.
Re^4: matching pdl elements
by Blue_eyed_son (Sexton) on Sep 14, 2008 at 16:35 UTC
    Thank you--the example was very helpful. Here's what I wanted to do (and a possibly inelegant formulation of a solution):
    perldl> p $a=sequence(5) [0 1 2 3 4] perldl> p $b=pdl(1,4,9,9,16) [1 4 9 9 16] **** To get the index of values in $a that can be found anywhere in $b +: perldl> $d=which(maximum (($a==$b->dummy)->xchg(0,1))!=0) perldl> p $d [1 4]
      Holy obfuscation, Batman!

      That seems to work. You could choose to use that (and hopefully leave a comment above it in your script). But you can get rid of some cruft there.

      First, as mentioned before, the dummy dim on $b is arbitrary. Using xchg when you already got to pick the dims is silly.
      which( maximum( ($a->dummy == $b) ) != 0)
      Maximum is a good choice. Like summation, it folds over a dimension in a way that works like logical or. But the inequality is unnecessary. All non-zero values are true. which already handles this.
      which( maximum( $a->dummy == $b ) )
      Thats about as good as any solutions I could give you. You'll still need a comment, but its a little easier on the eyes.

      For comparison purposes, here's the solutions I was expecting:
      # The one I basically handed you. Catches duplicates. $c = which( $a == $b->dummy ) % $a->dim(0); # Switching up the dims. Basically same as above. $c = which( $a->dummy == $b ) / $b->dim(0); # Using summation. Like yours, ignores duplicates. $c = which( sumover( $a->dummy == $b ) );
      They are no more understandable than your solution (once trimmed).