Mapbox-gl-js: An expression to check if an array contains a given value

Created on 11 May 2017  路  20Comments  路  Source: mapbox/mapbox-gl-js

Example:
A feature has properties:

{ colors: ['red', 'green', 'blue'  }

now, I want to filter the features that has one or more of the colors I want to filter on.

filter: ['any', ['inArray', 'colors', 'green'], ['inArray', 'colors', 'blue'] ]

or

filter: [ '!inArray', 'colors', 'green' ]

It seems like the inverse variant of the membership filter 'in' and '!in'

feature

Most helpful comment

GeoJSON properties do support arrays, and we have support for parsing them, so I think accessing them as part of the expression syntax is something we should also incorporate.

All 20 comments

Yes, I have run into this need as well. The use case was a map of events, where each event had several categories. I would like to do:

{ categories: ['Arts','Money','Sport'] }

and

filter: ['inArray', 'categories','Sport']

The workaround in my case was to split all the categories out:

sportCategory:true, artCategory: true, moneyCategory: true

I think that workaround is probably always possible, although it would get cumbersome for large sets.

Yeah, for my use case, it will be an evergrowing large set of IDs. For example:
{ categories: [32,44,53,66,235,434] }

So filtering on boolean values is not an option :/

4715 will help with one aspect of this, but actually I think the more challenging issue is that the vector tile specification does not support arrays or objects as feature property values. (See https://github.com/mapbox/mapbox-gl-js/issues/2434, https://github.com/mapbox/vector-tile-spec/issues/75)

Oh, doesn't support arrays or objects, that's a kinky thing to work around :/

Ok, how about a function to match a concated string using regex? :p

So, in my case (https://github.com/mapbox/mapbox-gl-js/issues/4698#issuecomment-300782931)
Instead of the array
{ categories: [32,44,53,66,235,434] }
it would be:
{ categoriesStr: '|32|44|53|66|235|434|' }

and filter:

filter: ['regex', 'categoriesStr', /\|44\|/, true] //Looking in the string to match the string '\|44\|'

The boolean at the end could be used to easily inverse the filter?

Just throwing out ideas here...

GeoJSON properties do support arrays, and we have support for parsing them, so I think accessing them as part of the expression syntax is something we should also incorporate.

Ok, how about a function to match a concated string using regex? :p

Tracked in mapbox/mapbox-gl-js#4089.

Related: #2434

@anandthakker a feature request, not a bug?

Whoops, my mistake - thanks @stevage

I don't think that in operator solves this problem...

Since the first parameter should be the _feature property name_ (string), it is not possible to change the parameters order, like:
['in', 'green', 'colors'] (different behavior)

A contains operator that evaluates the existence of a string in a feature property _which type is an array_ could help...

@gabrielmsdiniz I think I'm confused because what you're describing sounds like what the in operator does.

If you have a feature

{
    'type': 'Feature',
    'geometry': {
        'type': 'Point',
        'coordinates': [
            -77.03238901390978,
            38.913188059745586
        ]
    },
    'properties': {
        'colors': ['red', 'green', 'blue']
    }
}

you could use ['in', 'green', 'colors'] to determine if the string green is in the property colors which is of type array. I'm not sure how the order of the arguments makes a difference.

@ryanhamley I don't know why, but I can't do it...
https://jsfiddle.net/gabrielmsd/q4zndpmh/5/

@gabrielmsdiniz The filter syntax has been deprecated; it will still work but you can't mix the filter syntax with the newer expression syntax.
Screen Shot 2020-01-13 at 5 00 55 PM

You'd probably want something like a case expression with in sub-expressions.

'circle-radius': ['case',
    ['in', 'green', 'colors'], 7,
    ['in', 'black', 'colors'], 10,
    ...
]

That being said, the filter docs are confusing because they reference an old in function which was removed from GL JS a long time ago. The docs need to be updated to remove those references since they _do not_ refer to the new in expression. Sorry for that confusion.

@ryanhamley Yes, I'd like to do something like this:

'filter': ['any',
    ['in', 'green', ['get', 'colors']],
    ['in', 'red', ['get', 'colors']]
]

So, how am I supposed to solve this without using filter?

The docs need to be updated to remove those references since they do not refer to the new in expression.

Wait, there's a new "in" expression that does exactly what this issue is requesting? But it's not documented?

@stevage Yes, it was implemented in https://github.com/mapbox/mapbox-gl-js/pull/8876 Here's an example I made https://codepen.io/rsh412/pen/yLygeZR

I didn't realize that it wasn't appearing in the docs. It was added in the PR so I'm going to have to dig into this to figure out what's up. Obviously we need to retool the docs a bit around this expression. Sorry for the confusion.

cc @mapbox/docs

Oh, cool! I really should start keeping an eye on https://github.com/mapbox/mapbox-gl-js/blob/master/CHANGELOG.md

@ryanhamley Yes, I'd like to do something like this:

'filter': ['any',
    ['in', 'green', ['get', 'colors']],
    ['in', 'red', ['get', 'colors']]
]

So, how am I supposed to solve this without using filter?

Did you ever get an answer? I am having a similar problem where my "in" expression filter is not reading my property array.

@gabrielmsdiniz @ColeAmodeo The functionality you're attempting to do is possible. See https://jsfiddle.net/rsh412/hue2783p/1/ The original fiddle posted in an earlier comment that appeared not to work was using GL JS 1.4.1 but the in operator was not added until 1.6.0. Newer versions of GL JS should work as expected. If you believe there's a bug, please open a new ticket with a reproducible test case.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

rigoneri picture rigoneri  路  3Comments

BernhardRode picture BernhardRode  路  3Comments

aaronlidman picture aaronlidman  路  3Comments

aderaaij picture aderaaij  路  3Comments

yoursweater picture yoursweater  路  3Comments