Julia: make KeyIterator and ValueIterator more array-like

Created on 5 Feb 2015  ·  9Comments  ·  Source: JuliaLang/julia

When have d = Dict(:foo => 12.34, "bar" => 567) and you write keys(d) you get a Base.KeyIterator object, which is fast and cheap to construct from the dictionary d. You can write collect(keys(d)) to get an array of keys, but you have to do this unfortunately often. It would be a good self-contained project to add more array-like behaviors to KeyIterator and the corresponding ValueIterator types so that things like keys(d)[1] and values(d)[end] work as expected.

help wanted

Most helpful comment

I think there are really two distinct things here: being able to index these objects, and getting broadcast to work as expected (which is really what #19577 is about).

I think broadcast should perhaps be the higher priority. While indexing is missing functionality that would require data structure changes to be efficient, broadcast currently behaves in an unexpected way. For instance,

julia> a = Dict(1=>2, 2=>2)
Dict{Int64,Int64} with 2 entries:
  2 => 2
  1 => 2

julia> all(collect(values(a)) .== 2)
true

julia> all(values(a) .== 2)
false

All 9 comments

The problem is that this indexing would be O(n).

I feel that the Iterator name itself is a bit unfortunate as the iterator could possibly be infinite so iterator(n)[end] would not really be meaningful.

Would be addressed by the ordered dictionary design that PyPy recently adopted:

http://morepypy.blogspot.com/2015/01/faster-more-memory-efficient-and-more.html

Julia Dev discussion:

https://groups.google.com/forum/#!searchin/julia-dev/pypy$20ordered$20dict/julia-dev/-5tofATwsgc/eDwD6bIvPw0J

In the case of dictionaries, these iterators can't be infinite...

Of course, but I feel that there is a component of API predictability. If I get an *Iterator object back, I would expect O(n) cost at getting the nth element and no guarantee that the iterator has a finite number of elements.

Should we have a kind of an iterator class hierarchy like C++?

Although we might ultimately want ordered dictionaries, I don't think it's good to set the expectation that a type like KeyIterator should implement indexing. For many data structures you can only efficiently iterate the keys, and not index them.

I think there are really two distinct things here: being able to index these objects, and getting broadcast to work as expected (which is really what #19577 is about).

I think broadcast should perhaps be the higher priority. While indexing is missing functionality that would require data structure changes to be efficient, broadcast currently behaves in an unexpected way. For instance,

julia> a = Dict(1=>2, 2=>2)
Dict{Int64,Int64} with 2 entries:
  2 => 2
  1 => 2

julia> all(collect(values(a)) .== 2)
true

julia> all(values(a) .== 2)
false

Also #18618

Was this page helpful?
0 / 5 - 0 ratings