Filter a list of list based on data

306 Views Asked by At

I've this data

      x ← ((1 'data1') (0 'data2') (0 'data3') (1 'data4') )
      x
┌─────────┬─────────┬─────────┬─────────┐
│┌─┬─────┐│┌─┬─────┐│┌─┬─────┐│┌─┬─────┐│
││1│data1│││0│data2│││0│data3│││1│data4││
│└─┴─────┘│└─┴─────┘│└─┴─────┘│└─┴─────┘│
└─────────┴─────────┴─────────┴─────────┘

I would like to filter the array like this

┌─────────┬─────────┐
│┌─┬─────┐│┌─┬─────┐│
││1│data1│││1│data4││
│└─┴─────┘│└─┴─────┘│
└─────────┴─────────┘

How can I achieve this?

I've tried this but it didn't work, it takes in account the first element only.

      ((⊃y)[1])/y←x
┌─────────┬─────────┬─────────┬─────────┐
│┌─┬─────┐│┌─┬─────┐│┌─┬─────┐│┌─┬─────┐│
││1│data1│││0│data2│││0│data3│││1│data4││
│└─┴─────┘│└─┴─────┘│└─┴─────┘│└─┴─────┘│
└─────────┴─────────┴─────────┴─────────┘
1

There are 1 best solutions below

2
Adám On BEST ANSWER

Good news is that you got it almost right. Not bad for your first day of APL!

This minimal change to your code will do the trick:

      ((⊃¨y)=1)/y←x
┌─────────┬─────────┐
│┌─┬─────┐│┌─┬─────┐│
││1│data1│││1│data4││
│└─┴─────┘│└─┴─────┘│
└─────────┴─────────┘

However, there's no need to make a copy of x into y, since APL is normally pass-by-value. Furthermore, = is commutative, so we can get rid of the inner parenthesis:

      (1=⊃¨x)/x
┌─────────┬─────────┐
│┌─┬─────┐│┌─┬─────┐│
││1│data1│││1│data4││
│└─┴─────┘│└─┴─────┘│
└─────────┴─────────┘

You can then assign this to y:

      y← (1=⊃¨x)/x
      y
┌─────────┬─────────┐
│┌─┬─────┐│┌─┬─────┐│
││1│data1│││1│data4││
│└─┴─────┘│└─┴─────┘│
└─────────┴─────────┘

In fact, we can get rid of the outer parenthesis too, by explicitly commuting /:

      x/⍨1=⊃¨x
┌─────────┬─────────┐
│┌─┬─────┐│┌─┬─────┐│
││1│data1│││1│data4││
│└─┴─────┘│└─┴─────┘│
└─────────┴─────────┘

Alternatively, we can make y a copy of x and then filter y in-place:

      y/⍨←1=⊃¨y←x
      y
┌─────────┬─────────┐
│┌─┬─────┐│┌─┬─────┐│
││1│data1│││1│data4││
│└─┴─────┘│└─┴─────┘│
└─────────┴─────────┘