Select to view content in your preferred language

Arcade: Select Similar items when item in selected

686
3
Jump to solution
04-21-2023 01:27 PM
Labels (3)
ThomasColson
MVP Frequent Contributor

In an AGOL webmap, I have an Attribute Expression (that I sourced from here😞

 

// get the states layer
var portal = Portal('https://arcgis.com')
var states = FeatureSetByPortalItem(
    portal,
    'a454cf97c4264cd2b77f27175e01d3ba',
    3,
    ['ABBRV']
)

// intersect feature with States
var xs = Intersects(
    $feature,
    states
)

// create array of intersected state names
var c_array = []

for (var c in xs){
    Push(c_array, c['ABBRV'])
}

// remove duplicates
var unique_states = Distinct(c_array)

// concatenate array, return string

return Concatenate(unique_states, ', ')

That works as expected: user clicks on a line, pop-up returns a list of state(s) that the selected line intersects. 

Here's the problem: the line is multiple parts (features? Sections?). CHunked up by numerous attributes (state, county, district, etc....). So if the user clicks on a line segment, they get the state(s) that the segment intersects. 

But what I want is: 

Every single state the ENTIRE line intersects, based on the name of the line. So if the NAME attribute of the line they click on is "BIGFOOT", some sort of magical arcade thing that FIRST selects every single line segment (which could be dozens) with NAME = "BIGFOOT", then do the intersect and return every state intersected by every line segment where NAME = "BIGFOOT".

Tags (2)
0 Kudos
1 Solution

Accepted Solutions
JohannesLindner
MVP Frequent Contributor

the line is multiple parts (features? Sections?)

I'd vote for "features". "parts" makes it sound like you're working with multipart geometries, and the expression should work as expected there.

 

To do what you want, you need to modify Josh's expression a bit:

  • load the line layer (the same layer for which you define this expression)
  • filter it to get all lines with the same name as the current $feature
  • create an outer loop that iterates over those lines, do the intersection for each line
// get the states layer
var portal = Portal('https://arcgis.com')
var states = FeatureSetByPortalItem(
    portal,
    'a454cf97c4264cd2b77f27175e01d3ba',
    3,
    ['ABBRV']
)

// get the lines layer
var lines = FeatureSetByPortalItem(
    portal,
    'id',
    0,
    ['NAME']
)

// get all lines that have the same NAME as the current $feature
var name = $feature.NAME
var filtered_lines = Filter(lines, "NAME = @name")

// create array of intersected state names
var c_array = []

// iterate over the filtered lines
for(var f in filtered_lines) {
    // intersect that line with the states
    var xs = Intersects(f, states)
    // get the intersected states' names
    for (var c in xs){
        Push(c_array, c['ABBRV'])
    }
}

// remove duplicates
var unique_states = Distinct(c_array)

// concatenate array, return string
return Concatenate(unique_states, ', ')

Have a great day!
Johannes

View solution in original post

3 Replies
JohannesLindner
MVP Frequent Contributor

the line is multiple parts (features? Sections?)

I'd vote for "features". "parts" makes it sound like you're working with multipart geometries, and the expression should work as expected there.

 

To do what you want, you need to modify Josh's expression a bit:

  • load the line layer (the same layer for which you define this expression)
  • filter it to get all lines with the same name as the current $feature
  • create an outer loop that iterates over those lines, do the intersection for each line
// get the states layer
var portal = Portal('https://arcgis.com')
var states = FeatureSetByPortalItem(
    portal,
    'a454cf97c4264cd2b77f27175e01d3ba',
    3,
    ['ABBRV']
)

// get the lines layer
var lines = FeatureSetByPortalItem(
    portal,
    'id',
    0,
    ['NAME']
)

// get all lines that have the same NAME as the current $feature
var name = $feature.NAME
var filtered_lines = Filter(lines, "NAME = @name")

// create array of intersected state names
var c_array = []

// iterate over the filtered lines
for(var f in filtered_lines) {
    // intersect that line with the states
    var xs = Intersects(f, states)
    // get the intersected states' names
    for (var c in xs){
        Push(c_array, c['ABBRV'])
    }
}

// remove duplicates
var unique_states = Distinct(c_array)

// concatenate array, return string
return Concatenate(unique_states, ', ')

Have a great day!
Johannes
ThomasColson
MVP Frequent Contributor

That worked perfectly! 

Sadly, performance is....lacking. 

Eg. I have a line with 36 features that passed thru 3 states. The result (pop up) takes 2-3 minutes to execute, on a very fast computer and very fast internet. Is this just a hard limitation of Arcade that can't be worked around?

0 Kudos
JohannesLindner
MVP Frequent Contributor

I guess (!) this is another case of this phenomenon, where accessing a featureset for the first time takes a lot of time. If that is the case, then the number of lines and states for a particular trail doesn't really matter, only the total number of lines and states.

But 2-3 minutes is really excessive. Sadly, I don't really have an idea for making it faster right now. Maybe consider precomputing those numbers, as they seem to be static.


Have a great day!
Johannes