-
-
Notifications
You must be signed in to change notification settings - Fork 5.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
map for Dict #5794
Comments
Currently, map for dictionary arguments falls back to the general iterable case. I'm not sure I see a difference between the status quo and what you are looking for. Does this not work the way you'd like it to?
This is very nearly your first suggestion, effectively like |
It would be more convenient if the key and value were provided as separate arguments instead of as a pair. Of course, then mapping with the identity function doesn't produce an equal Dict, but I think that may well be ok. Another issue is what to do about key collisions. |
Yeah, I see. And this was a little surprising to me:
Perhaps the iters… map method should check to see if they're all done at the end? Oh! I see this came from the mailing list: https://groups.google.com/forum/?fromgroups=#!topic/julia-users/naGp9DUdSq8 |
How should we distinguish between a Should The more general problem is: what about functions where you want to specify the return type - but the parameter types are identical? Is there a Julian solution for this problem - one being the |
I believe there is a dictionary constructor from an iterable of tuples now, so while the whole thing could be done more efficiently, constructing a Dict is pretty straightforward if that's what you want. Might need better docs (I haven't checked). |
So we definitely need a specific associative method, since currently the type information gets dropped: function f() # to avoid global-induced Any types
local a = ["a"=>1, "b"=>2] # Dict{ASCIIString,Int64}
which(map, kv->kv, a) # map(f::Union(DataType,Function),iters...) at abstractarray.jl:1265
local m = map(kv->kv, a) # Array{Any,1}
end I was actually expecting (edit: it seems that anonymous functions are another reason the type information gets dropped) Would Dict(map(kv->(k[1], v[2]+1), ["a"=>1, "b"=>2]))
Dict(map(k->k, v->v+1, ["a"=>1, "b"=>2]))
Dict(map(v->v+1, ["a"=>1, "b"=>2])) |
Is it possible to constrain Function parameters? Looking at doing a Base.map{K,V,KR,VR}(f::((K,V)->(KR,VR)), d::Associative{K,V}) # produces an Associative{KR,VR} Note: not saying this specific example is a good idea, just asking generally about constraining functions. |
This function would at least get typed correctly (as opposed to the iter-based function) map{K,V}(f::Callable, d::Associative{K,V}) = [f(k,v) for (k,v) in d] Then you wrap the return in a Of course anonymous functions have issues with preserving type information in comprehensions, which seems why My leaning is to implement the above with a comprehension, and use inline functions (not anonymous syntax). Then I have a hope of getting correctly types out even when an empty array is fed in. The current |
I just ran into this problem. Given the functional nature of Julia and its native collections, this should be implemented ASAP:
I don't think the syntax is perfect, but you get the idea. You should look to Scala, as those guys have gotten it down, Map (equivalent to Julia's Dict) in particular. The other available functions that are missing in Julia should also be added, like flatMap which excludes all null value Nullable objects (Scala's equivalent is Option). http://www.scala-lang.org/api/current/scala/collection/Map.html http://www.scala-lang.org/api/current/index.html#scala.Option |
Thanks for the input, @BryanARivera. Any chance you could start a pull request? That would be the best way for this to get implemented ASAP. Most people working on Julia right now aren't focused on this area, but most are willing to review pull requests. Also, consider opening an issue (and/or pull request) at Cheers! |
@kmsquire Hopefully I will have the chance to delve into it soon. I will try to implement everything I can as Scala's collections are quite central to the language. I envision it would accelerate Julia dev as well. Should be relatively straightforward. Scala has got the naming and function conventions down, we just need to rebuild it in Julia. Would |
@BryanARivera, that sounds fantastic. I'm also a huge fan of Scala's Collections framework. DataStructures is probably the right place, but if what you want to implement is very different than what is already there, it might turn out that a new package would be better. But let's start in DataStructures.jl and see where that goes. Cheers! |
@BryanARivera I'm very happy to have read this since I too have been looking for a
since it could break existing code (unless someone like @StefanKarpinski thinks this is a good move?). In any case, functions which return We'll probably need both |
I would be happy to write a PR. Does this look OK:
It won't have the best performance until Jeff is done with his anon functions improvements. |
We don't usually camel-case function names in base. |
Also, you don't really need that second function. Just do: mapvalues(f, d::Associative) = map(p->f(p.second), d) Sounds like a nice addition to me (as well as But that wouldn't return a |
@nalimilan I see - it's on my todo list. |
This works, but doesn't look optimized:
|
Is there any way to specify a function return type so that this will work?
|
As I said, I think you should first write Base.similar{K,V}(d::Dict, ::Type{Pair{K,V}}) = Dict{K,V}()
function Base.map(f, a::Associative)
if isempty(a)
return similar(a)
end
st = start(a)
a1, st = next(a, st)
first = f(a1)
dest = similar(a, typeof(first))
sizehint!(dest, length(a))
push!(dest, first)
while !done(a, st)
el, st = next(a, st)
push!(dest, f(el))
end
dest
end
mapvalues(f, a::Associative) = map(p->p.first=>f(p.second), a) I'm not sure about the case where the dict is empty: the existing |
My code would have to be adapted a bit if we want to write |
FWIW, Haskell defines its
In both cases (array or associative), the function takes only the value (in the key-value pairs) and returns a new value for the same key. |
I was surprised recently by the current behavior of So while I agree that the view on arrays as associative containers is nice, I'm not sure if this should take precedence over the differences between how they are iterated. (Or would we want to bring that in line between dicts and arrays? It's a major breaking change) |
I agree that consistency with what iteration over a |
Part of #20402 |
Deprecation is in; a new |
@JeffBezanson as you are the assignee of this, I have reviewed it an I think that it is covered by current functionality so it should likely be closed. |
We should go back to the old behavour.
If we wanted map to work on values if we want a map that returns a dict I think it is good to be able to thing of
when |
What if it was lazy and produced a pair generator? My reasoning is that you really never want a vector of pairs, you always want to do something with that vector of pairs: put it in a |
It is an interesting point, For example
I don't think that should return anything with the |
If we wanted a map to work on pairs then we should be able to do IMO, we'd ideally just iterate/map/etc over values, and require So now we're stuck in this weird never-never land where |
Options include:
Any of these options also open us up to having |
I kind of think we should clean this up in Julia 2.0. It appears to me that a unified solution is likely to involve at least some breaking changes, and adding new functionality to Julia 1.x only increases the impact of any potential changes to the API. (Also - I haven't been following closely for a while, but was there any thoughts on how many more 1.x releases there will be before we work on 2.0?) |
@StefanKarpinski Can we start this by defining map(f, itrs...) = Base.Generator(f, itrs...) in using Base.Iterators: map, filter, flatten as kind of
@oxinabox Does it return a |
(Sorry to kick up dust) |
For others reading this thread, I want to point out what ideally should have been mentioned explicitly in a comment above, namely, that |
I noticed there wasn't any
map
methods that generatedDict
s. Which function/name - comments please:To distinguish the above from the current
map
(which you still may want to use), they will need new names - suggestions?I noticed that
map
forArray
s handles multiple arrays - presumably this is more of a join-by-key semantic for Dicts and therefore not needed inmap
forDict
s?The text was updated successfully, but these errors were encountered: