Arcade and pop-ups, Replace function issues with 1 char strings

1485
7
03-28-2019 02:52 PM
KateCarlson
Occasional Contributor

Hi-  I wrote a simple arcade script to replace text in a field for the pop-up display and have run into something unusual.

The script will replace the abbreviated name for impairment type with the full name for each hydro feature in the layer.

var impParam = $feature["IMP_PARAM"];

impParam = Replace(impParam, 'FishesBio', 'Fishes bioassessments');
impParam = Replace(impParam, 'Hg-F', 'Mercury in fish tissue');
impParam = Replace(impParam, 'E.coli', 'Escherichia coli');
impParam = Replace(impParam, 'InvertBio', 'Aquatic macroinvertebrate bioassessments');
impParam = Replace(impParam, 'TSS', 'Total Suspended solids');
impParam = Replace(impParam, 'T', 'Turbidity');

return impParam;

Some features have several impairments listed, example:

It works great except that the Replace function will not replace 1 character strings, such as the 'T' for 'Turbidity', AGOL doesn't like it at all and will stall out forcing me to reload the page.  Any ideas why I cannot replace a 1 char string or any suggestions for improving the script?

Thanks much!

Kate

Tags (1)
0 Kudos
7 Replies
StephenM
Occasional Contributor II

I think the issue is that the replacement for 'T' has a 'T' in it, so it creates a sort of endless loop that freezes the page. The 'T' in other values like 'TSS' or 'Total Suspended solids' (depending on the order of the replace statements) will also be replaced, so that's something else to consider. Since Arcade expressions are case sensitive the lower case t's aren't affected.

You could do something like this:

var impParam = $feature["IMP_PARAM"];

impParam = Replace(impParam, 'T', 'turbidity');
impParam = Replace(impParam, 'FishesBio', 'Fishes bioassessments');
impParam = Replace(impParam, 'Hg-F', 'Mercury in fish tissue');
impParam = Replace(impParam, 'E.coli', 'Escherichia coli');
impParam = Replace(impParam, 'InvertBio', 'Aquatic macroinvertebrate bioassessments');
impParam = Replace(impParam, 'turbiditySS', 'Total Suspended solids');
impParam = Replace(impParam, 'turbidity', 'Turbidity');

return impParam;‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍
KateCarlson
Occasional Contributor

That's it!!  Thank you, Stephen, for taking the time to explain along with an example solution.

Kate

0 Kudos
XanderBakker
Esri Esteemed Contributor

Although the solution provided by Stephen works in your specific case, you should be aware that Replace is not the correct function to solve this. Replace will find and replace any coincidence of the string that you are looking for which potentially may cause unexpected behavior.  You actually have a list of values separated by a semicolon. What would be better (although it is more complex) is to test if any of the values in the list exactly matches the list of values that you have. See the example below:

// var impParam = $feature["IMP_PARAM"];
var impParam = "Test; E.coli; TSS; T; InvertBio; turbiditySS; turbidity; FishesBio; Hg-F";

var dict = {
    'T': 'turbidity',
    'FishesBio': 'Fishes bioassessments',
    'Hg-F': 'Mercury in fish tissue',
    'E.coli': 'Escherichia coli',
    'InvertBio': 'Aquatic macroinvertebrate bioassessments',
    'turbiditySS': 'Total Suspended solids',
    'turbidity': 'Turbidity'
}

var lst_in = Split(impParam, ';');
var lst_out = [];
for (var i in lst_in) {
    var item_in = Trim(lst_in[i]);
    var item_out = item_in;
    for (var search_txt in dict) {
        var replace_txt = dict[search_txt];
        if (item_in == search_txt) {
            item_out = replace_txt;
        }    
    }
    lst_out[i] = item_out;
}

var result = Concatenate(lst_out, "; ");
return result;

In this case I create a dictionary with search and replace values (lines 4 - 12). The code creates a list on line 14 and starts to loop through the items of the list and will validate any value in the dictionary and replace it by the desired one.

At the end (line 28) the items of new list are concatenated to create the output string.

KateCarlson
Occasional Contributor

Xander-

Thanks for responding with a 'best practice' solution.  You are right, the Replace function is working for my needs but I would rather use the more sophisticated method to ensure this is done right. 

I copied and pasted your example script and it does work, but, it returns/replaces everything listed in the var impParam, even Test.  Perhaps as a test, this is what it was supposed to do?  Any recommendations for returning only the values for each record, such as 'Eschreichai coli; Turbidity' in the first record.

Thanks much-

Kate

0 Kudos
XanderBakker
Esri Esteemed Contributor

I suppose you didn't unquote line 1 and removed line 2. Line 2 I used for testing. Line 1, once unquoted,  will read your field.

KateCarlson
Occasional Contributor

That's right, amateur script-er here!  Thanks, this works great.

Kate

0 Kudos
by Anonymous User
Not applicable

Xander - thanks for the great solution (and many others I've seen!).

I made a slight modification to use the HasKey dictionary method:

var impParam = "Test; E.coli; TSS; T; InvertBio; turbiditySS; turbidity; FishesBio; Hg-F";

var dict = {
    'T': 'turbidity',
    'FishesBio': 'Fishes bioassessments',
    'Hg-F': 'Mercury in fish tissue',
    'E.coli': 'Escherichia coli',
    'InvertBio': 'Aquatic macroinvertebrate bioassessments',
    'turbiditySS': 'Total Suspended solids',
    'turbidity': 'Turbidity'
}

var lst_in = Split(impParam, ';');
var lst_out = [];
for (var i in lst_in) {
    var item_in = Trim(lst_in[i]);
    var item_out = item_in;
    
    if ( HasKey(dict, item_in) ) {
        item_out = dict[item_in];    
    } // else - item_out still equals item_in
    
    lst_out[i] = item_out;
}

var result = Concatenate(lst_out, "; ");
return result;