geodesk-py
geodesk-py copied to clipboard
Creating feature set from features
Suppose I’ve done some filtering that I couldn’t do in Geodesk and GQOL, so I’ve done some version of [a for a in list(areas) if xyz]. Now I want to do an operation on the resulting set that I would know how to do if I had a feature set.
I can’t figure out how to get my list of nodes back into a Features object so I can use contains and other things I can do with feature sets.
There could be many ways to solve my problem.. if there was, for example,
- a constructor for Features that takes a list of Feature objects and returns a feature set (then I could turn my list back into a feature set)
- a way to pass an anonymous function to a feature set and return a new feature set filtered by whether the anonymous function returns true (then I could do a lot more without turning the feature set into a list or Python set)
- a way to create an empty feature set and add features one by one
- a way in GQOL to select an object with a specific id, similar to how you can do way(12345) in Overpass
It looks like none of these options exist (yet)? Sorry I may have overlooked something obvious.
You are correct, these capabilities don't currently exist. We've considered adding them, here are some thoughts:
-
Unlike
setobjects in Python, feature sets aren't "true" collections; they don't contain any features, they are merely lightweight descriptors, telling the query engine what should be retrieved from the GOL. This makes them very efficient, and you can copy/pass them around without having to worry about memory consumption. On the flip side, there is no way to "add" features to a set -
We've considered allowing arbitrary Python functions (or anonymous lambdas) to be used as filters for a feature set. However, it may be more intuitive to just use a set (or list) comprehension:
[ f for f in features if <your condition> ] -
Feature sets are currently missing support for
__contains__(i.e. theinoperator); this is coming (#23) and should address your use case where you have your own collection of features and want to test them against the matchers/filters of a feature set:[ f for f in your_collection if f in feature_set ] -
We're considering feature lookup by ID (#24) (Main obstacle here is the lack of an ID-based index which would speed these queries significantly, but consumes a relatively large amount of storage)
Thanks for considering this!
It's true that I can use [ f for f in features if <your condition> ] or (lazy version) filter(<my function>, features). But these return a list and an iterator, respectively. It means I no longer have access to the convenient functions that feature sets have. For example if I want to map the results I can't just do results.map, I have to write a loop; if I want to write to GeoJSON I can't just to results.geojson.save, I have to look up the GeoJSON syntax and write a helper function. This is not the end of the world but it would be more convenient if I was able to do this in one line with something like features.filter(<my function>).map etc.
Yes, you raised some very good points. I've created two individual enhancement items:
- #25
- #26
Both have different challenges and limitations, but we should be able to at least implement one of these in the next major release.