Julia: Method for dropping an element of NamedTuple

Created on 14 Jun 2018  ยท  11Comments  ยท  Source: JuliaLang/julia

I am trying to do:

d = (solver = 2, b = 3)
f = same tuple as d but without :solver 

The JuliaData/NamedTuples has a delete method, so one can do something like f = delete(d, :solver). It would be nice to have it for Core.NamedTuple as well, if possible.

Most helpful comment

Base has my permission.

All 11 comments

Current workaround:

julia> d = (solver = 2, b = 3, c = 4)
(solver = 2, b = 3, c = 4)

julia> inter = [p for p in pairs(d) if p[1] != :solver]
2-element Array{Pair{Symbol,Int64},1}:
 :b => 3
 :c => 4

julia> f = (; inter...)
(b = 3, c = 4)

(answered on Slack, I think by araslan)

julia> function dropnames(namedtuple::NamedTuple, names::Tuple{Vararg{Symbol}}) 
            keepnames = Base.diff_names(Base._nt_names(namedtuple), names)
           return NamedTuple{keepnames}(namedtuple)
       end
dropnames (generic function with 1 method)

julia> d = (solver = 2, b = 3, c = 4)
(solver = 2, b = 3, c = 4)

julia> dropnames(d, (:solver,))
(b = 3,)

julia> dropnames(d, (:b,))
(solver = 2,)

julia> dropnames(d, (:b,:solver))
NamedTuple()

julia> dropnames(d, (:oops,))
(solver = 2, b = 3)

Very nice! Can it also become part of Base or I am being too greedy?

Base has my permission.

Is the inference failure OK (everything becomes Any)?

I would imagine that most use-cases could get away with @generated and val-type symbols (the symbol to drop is a source-code literal). On the other hand, I'd imagine that most uses are not performance critical.

There are some utilities for implementing this in base/namedtuple.jl. If diff_names is used to remove the requested name(s) then @JeffreySarnoff's implementation will be inferable.

dropnames implementation improved ^^

@JeffreySarnoff Will you do a PR for this?

(I really hope that this is in the next beta :P )

I don't know what to do about this:

julia> function dropnames(namedtuple::NamedTuple, names::Tuple{Vararg{Symbol}}) 
            keepnames = Base.diff_names(Base._nt_names(namedtuple), names)
           return NamedTuple{keepnames}(namedtuple)
       end
julia> code_warntype(dropnames, (NamedTuple, Tuple{Vararg{Symbol}}))
Body::Any
1 1 โ”€ %1 = Base.diff_names::typeof(Base.diff_names)                                         โ”‚
  โ”‚   %2 = Base._nt_names::typeof(Base._nt_names)                                           โ”‚
  โ”‚   %3 = %2(%%namedtuple)::Any                                                            โ”‚
  โ”‚   %4 = %1(%3, %%names)::Tuple{Vararg{Symbol,N} where N}                                 โ”‚
2 โ”‚   %5 = Core.apply_type(Main.NamedTuple, %4)::Type{NamedTuple{_1,T} where T<:Tuple} where _1
  โ”‚   %6 = %5(%%namedtuple)::Any                                                            โ”‚
  โ””โ”€โ”€      return %6                                                                        โ”‚

That happens because NamedTuple is too abstract (in the cal to code_warntype).

Was this page helpful?
0 / 5 - 0 ratings

Related issues

yurivish picture yurivish  ยท  3Comments

wilburtownsend picture wilburtownsend  ยท  3Comments

felixrehren picture felixrehren  ยท  3Comments

m-j-w picture m-j-w  ยท  3Comments

TotalVerb picture TotalVerb  ยท  3Comments