Syntax for extracting keys from vector of pairs?

julia> X
3-element Vector{Pair{String, Any}}:
  "water" => [1 2]
 "coffee" => [3 4 5]
    "tea" => [6 7 8 9]

To extract the keys from X, the current syntax is first.(X). However, given that the syntax for extracting a column from a single pair uses indexing like this

julia> X[2][1]
"coffee"

julia> X[2][2]
1×3 Matrix{Int64}:
 3  4  5

wouldn’t a more “regular form” of the syntax to extract all keys be X.[1] instead of first.(X)?

See this discussion and issues linked therein:

1 Like

You can use a general index with getindex.

julia> getindex.(X, 1)
3-element Vector{String}:
 "water"
 "coffee"
 "tea"

julia> getindex.(X, 2)
3-element Vector{Matrix{Int64}}:
 [1 2]
 [3 4 5]
 [6 7 8 9]

If you use a dictionary instead of vector of pairs, you can get the keys with the keys function.

julia> using OrderedCollections

julia> Xdict = OrderedDict(X)
OrderedDict{String, Matrix{Int64}} with 3 entries:
  "water"  => [1 2]
  "coffee" => [3 4 5]
  "tea"    => [6 7 8 9]

julia> keys(Xdict)
KeySet for a OrderedDict{String, Matrix{Int64}} with 3 entries. Keys:
  "water"
  "coffee"
  "tea"

julia> values(Xdict)
ValueIterator for a OrderedDict{String, Matrix{Int64}} with 3 entries. Values:
  [1 2]
  [3 4 5]
  [6 7 8 9]

As of yesterday, Julia v1.13 has a new Iterators.nth that generalizes first and last. And it has a “functor” like form that you can broadcast:

julia> X = [
         "water" => [1 2]
        "coffee" => [3 4 5]
           "tea" => [6 7 8 9]];

julia> Iterators.nth(1).(X)
3-element Vector{String}:
 "water"
 "coffee"
 "tea"

julia> Iterators.nth(2).(X)
3-element Vector{Matrix{Int64}}:
 [1 2]
 [3 4 5]
 [6 7 8 9]

Yeah, I know it’s not as “pretty” as an indexing expression. But you can now easily make ordinal numbers work (albeit with parentheses or piping; the precedence of the function call “wins” over the juxtaposition):

julia> struct OrdinalIndicator; end

julia> Base.:*(i::Integer, ::OrdinalIndicator) = Iterators.nth(i)

julia> const ᵗʰ = const ʳᵈ = const ⁿᵈ = const ˢᵗ = OrdinalIndicator()
OrdinalIndicator()

julia> (1ˢᵗ).(X)
3-element Vector{String}:
 "water"
 "coffee"
 "tea"

julia> X .|> 2ⁿᵈ
3-element Vector{Matrix{Int64}}:
 [1 2]
 [3 4 5]
 [6 7 8 9]

(and yes, this is mostly a joke)

13 Likes

But a nice joke.
Another variant of it:

_¹ˢᵗ = Iterators.nth(1)
_²ⁿᵈ = Iterators.nth(2)
_³ʳᵈ = Iterators.nth(3)
_⁴ᵗʰ = Iterators.nth(4)
_⁵ᵗʰ = Iterators.nth(5)
# ...
1 Like