res ← keys (fn ##.key) list         ⍝ key operator

From Phil Last, this operator is modelled on the "key" adverb of J (u/.),
described thus ...

    "In (x u/. y), items of x specify keys for corresponding items of y
     and u is applied to each collection of y having identical keys."

The shape of the result is (⍴∪⍺) the order being that of the first occurrence of
    each item of (∪⍺)."

Technical notes:

A traditional implementation might look like:

  ∇ res←keys(fn key)list;key
    res←⍬
    :For key :In ∪keys
        res←res,⊂fn list/⍨keys∊⊂key
    :EndFor
  ∇

A first obvious D: coding might be to name the operands and run an inner
function on each unique item of keys.

    key←{
        keys←⍺
        fn←⍺⍺
        list←⍵
        {fn list/⍨keys∊⊂⍵}¨∪keys
    }

This does the job perfectly but the final coding makes use of the fact that
    parameter substitution is generally quicker than assignment.
As in the simple version above we need an inner function to run on each
    unique item of (⍺).
But we need the original three parameters in their entirity as well as a
    unique item of keys for each iteration.
By making the inner function a dyadic operator with its four operands we can
    represent (⍺) and (⍺⍺) as themselves, the current unique item as (⍵) and
the outer (⍵) as (⍵⍵).
We enclose the unique item (⍵) to counteract the implicit disclosure performed
    by (each).

    key←{
        (⊂⍺)⍺⍺{⍺⍺ ⍵⍵/⍨⍺∊⊂⍵}⍵¨∪⍺
    }

The final version is typically 20% faster than the traditional operator and
    5% faster than the verbose dynamic version.

Examples:

    abc ← 'abracadabra'

    abc +/ key 1
5 2 2 1 1

    +key∘⍳∘⍴⍨ abc
 1 4 6 8 11  2 9  3 10  5  7

    {(⊃⍵),⍴⍵}key⍨ abc
 a 5  b 2  r 2  c 1  d 1

See also: alists

Back to: contents

Back to: Dyalog APL

Trouble seeing APL font?