To avoid confusion with maps (used in levels as geometry), this is about the maps, used to store data.
The maps still lack some crucial functions, notably :
-Make map from 2 arrays
-Set Map Elem
-GetKey and GetValue as pure and reference
-Find returning the index
Explainations :
Make map from 2 Arrays: At runtime, you can’t just use Make Map (that actually requires you to input keys and index by hand), and since maps are basically two arrays, this makes sense
Set Map Elem: The current only way to modify a map is to remove the index then add it back, and that has quite a lot of performance overhead. You can’t just do a getValues then Set array Elem, because getValues doesn’t give the reference
GetKey and GetValue as pure and reference: Why not ? I know it can break the map if you remove an index in the array without removing the same in the other one, but that shouldn’t be an issue, just put a warning on it.
Find returning the index: It’s a find, and it’s two arrays, so when you’re using one of the arrays, you know where that is.
And this is why I’m not currently using maps but two arrays linked together by code, so that kinda sucks.
Map is NOT represented by two arrays in memory. It’s represented by some kind of binary tree for faster look-up.
So, point by point
making from two arrays, possible but it’ll be the same as you going over every key-value pair adding them one by one - write your own helper function for it and be happy.
modifying map by modifying result of GetValues - technically impossible as map is not stored in two arrays, GetValues cycles over binary tree gathering all the data in one array, unless you could have array of references and even then any addition or removal to map may invalidate whole references array due to map nature.
getting GetKeys and GetValues as references - same as above, technically impossible as map is not represented by two arrays and this two functions gather values from binary tree.
returning index in find - technically impossible as there are NO stable indexes in map, it’s ■■■■ binary tree, not two arrays inside, indexes may change on a whim after any map modification.
So, in general, you have to better understand what map is and what it’s used for (good example - FName as key and whatever as value) or continue to use two arrays as you do now. Sacrificing binary tree lookup speed for your convenience to have indexes where there are no indexes is not a way to go.
Adding the elements one at a time is slow and code-heavy
Having the arrays as pure makes you able to use Set Members in Struct and that’s useful. Also, it make it so that you could use SetArrayElem
The same applies to the arrays, and why not ? You can remove an index before and you’re still fine because you know what you removed. When the map remove something, it mirrors everything on the keys and the values, so everything else gets shifted in memory.
I looked inside Map code in engine sources, just to be sure. If simplified up to ignoring all complicated stuff - internal representation of map is ONE array of Pairs, each Pair holding key and value while all the fancy stuff around that array is used to find needed Pair faster. So when you request array of keys or array of values it just plain iterates over Pairs in array and copies keys or values depending on what was requested.
Not the same - with array you could predict what will change with 100% accuracy, while for Map it completely depends on what is currently inside of Map and can’t be clearly predicted without looking at internal state of Map.
Nope, it’s sparse array which could have “holes” in it, that’s why you can’t predict what will happen when you add new element without looking inside internal part of Map - will it be added to the end or will it fill one of the holes?
And that C part fully dictates what could be done and what can’t be done in blueprints. You can’t represent array of 2-component structs as two arrays and expect them to be capable to still influence structs in initial array. At least without witchcraft.
Well, even if it were pure array inside, it’ll not change the fact that it’s array of structs and so can’t be represented by two separate arrays without loosing ability to influence data in initial array, effectively making having indexes completely useless.
And, by the way, you don’t have access to sparse arrays in Blueprints if I remember correctly.
And another “by the way”: Blueprints performance is far from C++ performance so if you’re really concerned with performance - go for C++ code replacing Blueprints wherever possible. Unless you deploy to a platform that don’t support C++ projects, but then it’s completely different story.
I don’t get why some of you don’t want to have an utility function (a zip function essentially) for making a map out of two lists. It’s pretty common all around.
It’s just that “improvements” you are asking for go absolutely against Map working principles. You basically want two linked arrays container type and not Map. It’s like asking to make FNames editable in the same ways strings and texts are editable - QoL improvement definitely but goes against purpose of FName.
How do you know whether the two arrays aren’t related? Your reasoning boggles my mind. What if he has an API that only returns things in arrays and then the API serves related data from another endpoint that too serves arrays only? The API could return the arrays in such an order that array A index 1 always corresponds to array B index 1 and so on. There are countless of use cases for zipping two arrays into pairs or maps.
Do you guys really change map types you work with that often so you can’t deal with arrays-to-map packing with one macro/function per pair of key-value types you use?
im necro’ing this because its bugging me and i wish it wasnt marked as ‘wont do’ and the AnswerHub doesnt seem to exist any more
i just wanna make a simple macro for finding a map element…
example for example’s sake: