Having trouble with expression for turning a field into a list for using in a IN() expression

Iโ€™m trying to filter out some records by checking their ID column values against another columnโ€™s Enumlist (Ref Type) values.

When I use this expression and test it with the editor it works:

IN([linkLocalidad], INDEX(currentUser[localCSV], 1)
)

But when running it in the App it only brings records that match the first value of the Enumlist.

If I manually make a list of the Enumlist values like so:

IN([linkLocalidad], LIST(E01 , E02 , E03)
)

It works fine in the App.

I have tried a bunch of different ways of turning this โ€œINDEX(currentUser[localCSV], 1)โ€ into a list, but so far nothing seems to work.

Let me know what other Info you guys need to help me out.

Thanks in advance!

Solved Solved
0 30 659
1 ACCEPTED SOLUTION

Try:

in([linkLocalidad], Split(Concatenate(currentUser[localCSV]), " , "))


@Hamlet your original formula would only pull the first value from the Current_Userโ€™s [LocalCSV] column.

If you had, for example: {1, 2, 3, 4} in that list, your original formula (using index) might be pulling the first number, not the list-of-a-list

  • Sometimes things process differently on the device than they do in the editor
    • Maybe on the device, the list-of-a-list is being converted automatically - and that โ€˜automaticโ€™ action is getting in the wayโ€ฆ maybe. I dunno.

Try wrapping your list-of-a-list inside a concatenate() and see if that helps.

View solution in original post

30 REPLIES 30

You need Split

Tried SPLIT and the editor shows it working but not in the App

I am not sure I follow. This comment sounds as if you are trying to compare a list to a list. What value is stored in [linklocalidad]?

The IN function can only check that a single value is part of a List of Values:

IN(<single value>, <List of Values>)

You wonโ€™t be able to compare an EnumList to a List or a List to an EnumList - unless the left-hand side picks out a single value first:

IN(Index(<EnumList>, 1), <List of Values>)

OR

IN(Index(<List of Values>, 1), <EnumList>)

Can you describe the intended goal for your app?

Iโ€™m trying to make a Slice of a table by having the user select a few RefType Values from an Enumlist.

This is what it should look like when it works:

You can see different names on the first column.

But I keep getting this:

Even though the editor test shows it working:

You have to replace INDEX() with SPLIT()
INDEX is for just a value

App editor test shows that it works:

In App it comes out blank:

Check how the data is separated on the EnumList [localCSV]
You can post here the value inside of one of the rows that has more than one value.
Example:
If itโ€™s something like Data1,Data2,Data3 the item separator inside SPLIT() should be ","
If itโ€™s Data1, Data2, Data3 โ†’ ", "
Data1 , Data2 , Data3 โ†’ " , "
It depends on your โ€œItem separatorโ€ config for the EnumList [localCSV] column

Yep, I also checked this, and I have it set up as it should be and still problem remainsโ€ฆ

Actually there is a way to do this, itโ€™s just not very straightforward

  • It involves the use of INTERSECT(), to create a list of all common values between the lists, and IsNotBlank() to see if thereโ€™s anything in that resultant list.
    • If there is, then there are common elements between the lists.
IsNotBlank(INSTERSECT(
  list(1, 2, 3), 
  list(2, 4, 5)
))
  • Result: true
    • Meaning: there are common elements between the two lists
      • They both share a 2; so the INTERSECT() results in that number (becoming a list of just the number 2), and IsNotBlank() results in true

Hereโ€™s an example of a permission formula Iโ€™m using in an app (it controls when an action should be seen):

IsNotBlank(INTERSECT(
  list("Dev", "Admin"), 
Split(Concatenate(Current_User[User_Permissions]), " , ")
))
  • The action is visible to โ€œDevโ€ and โ€œAdminโ€ permissions types
  • If the Current_User has either of those inside their [User_Permissions], then the action is shown

Yes, I agree (and I still forget about INTERSECT())

โ€ฆwe still do not KNOW what is actually stored in [linkLocalidad].

@Hamlet Is [linkLocalidad] an EnumList with Base Type = REF??

[linkLocalidad] is just a Ref type field. Not Enumlist.

Yep, got it from the previous post. I missed a couple things from original post. The column [localCSV] is the EnumList of Refโ€™s and currentUser, I now assume, is a slice with only a single row of details for the currently logged in user. I didnโ€™t infer these details.

So, the basic issue here is that currentUser([localCSV]) is actually a List of a single item which is also a list. Your goal was to check that list ITEM (a list) and see if [linkLocalidad] was an included value.

Your final expression works because the CONCATENATE โ€œflattensโ€ the list into a single comma separated TEXT value. The SPLIT then transform that into a List again but this time just one list instead of a List of Lists.

What I donโ€™t understand is why didnโ€™t this expression below work? Shouldnโ€™t INDEX have returned the first List item - the column [localCSV] which is also a list?

IN([linkLocalidad], INDEX(currentUser[localCSV], 1))

By the way, when I use the currentUser slice technique, I access the values using the ANY function. So far I have not seen an issue. An example would be:

IN([linkLocalidad], ANY(currentUser[localCSV]))

Both your examples work on the Editor Test, but not on the App itself. Thatโ€™s what was throwing me off

I know, itโ€™s counterintuitive.
Since whatโ€™s inside the [localCSV] is a list also, Index just takes the first value from that list.
Is like a list of lists (eventhough there is just one row) and then index takes the first value.
In other words, INDEX() is just for values, not for lists
Thatโ€™s why I suggested the SPLIT() expression since it creates a list from [localCSV]

This didnโ€™t mesh with my understanding , so I have been playing with various ways to access an EnumList of Refโ€™s. The behavior seems completely as I would expect. I am not seeing the issues highlighted here.

In the Image below, I am showing a Form where I have chosen a REF value into an EnumList and then used that in 3 different versions of an IN function (labeled 1, 2, 3). To help show the complete function, I am also showing the resulting Lists compared to (red arrows). I am aware you canโ€™t see all details.

You will note that when I compare against CurrentUser[Choices], the test fails as indicated with a result of N. The other two tests, which pick off the first item from the CurrentUser[Choices] list Pass the test as indicated with a result = Y.

Iโ€™d also like to call your attention to the list results for Test List 1 and Test List 2. Notice how Test List 1 has NO spaces while the other Test Lists DO have spaces included? This is how AppSheet is distinguishing the list items. Test List 1 is a List of 1 item also a list. Test List 2 and Test List 3 are both a list of 4 items of distinct values.

Point is that the use of ANY and INDEX seem to work as expected without the need for CONCATENATE and SPLIT.

Example of List of Lists - Multiple list items. Note the placement of spaces to distinguish List items as lists
3X_9_2_9286449508cc81560bc5ee480103ec00fef4ad4b.png

Here is a Mind Blower!!

It appears that the IN function WILL compare Lists against other Lists!!! And more over, the order of the chosen list doesnโ€™t matter!!

In my Choice List, I have chosen multiple REF items and in reverse order of the lists I am comparing against. In all 3 variations of the test, the returned result was Y. Test 1 Result returned Y this time because its result matched the single list item of {1,2,5,7] though it is in reverse order.

The other 2 tests matched a list against a list.

If I then only choose 7 and 1, in that order. Test Result 1 is N as expected but the other 2 are still Y - compared list against list.

Choose a mix in lists and not in lists - all three fail - as expected

Choose none in common among lists - all 3 fail - as expected

Whoaโ€ฆcrazy.

Split and concatenateโ€ฆ expensive???

  • Starts shaking head in disagreement
    • Even with a big stringโ€ฆ I wouldnโ€™t think the time needed for the operation to process wouldnโ€™t be close to a brute force SELECT()???
    • Theyโ€™re only text-manipulation formulasโ€ฆ

This is exactly why they are expensive. Text operations are one the most expensive operations when compared to other data types. In this context there will need to be N-1 concatenations and then N-1 splits. Thatโ€™s 2(N-1) operations just to get to the point to perform the IN function. The IN could be another N-1 function depending on where the value sits in the list. Thatโ€™s a total of 3(N-1)

A similar SELECT would be simply N. But something that Big O doesnโ€™t really account for is the expense of the operations. Concatenating 2 text values is a lot more expensive than simply comparing those same text values.

My main point is that if a CONCATENATE/SPLIT are performed on large lists or even worse, lists that grow as the table grows, the impact of CONCATENATE/SPLIT will become huge. I believe its a performance hit that is not needed - or at least no longer needed in AppSheet.

I think that at this point we should be making a Feature Request so that AppSheet teams adds exactly how expensive each function on AppSheet is in the docs

This is interesting.
Have you tried with strigns?
A common scenario for me is:

  1. There is info from more than one company inside the App. Lets call this table Company
  2. There is a User table that has an EnumList base type Ref where I select wich Company's info the user can access to
  3. There is a Slice called Current_User where the row filter condition is [EMAIL_COLUMN]=USEREMAIL()
  4. There is a Security Filter where I need to use this expression in order to work:
IN(
  [A_COLUMN_THAT_HAS_THE_KEY_OF_COMPANY],
  SPLIT(
    CURRENT_USER[ENUMLIST_BASETYPE_REF],
    " , "
  )
)

Another example that could be easier to replicate

  1. There is an app that works as a launcher
  2. There is a table with AppSheet Apps
  3. There is a user table
  4. There is the same Current_User slice
  5. I allow the users just certain apps on the launcher view depending on a EnumList basetype ref
  6. The users just see the Apps that are allowed base on security filter

Now, maybe there was a bug related to how IN() was dealing with this list-of-lists scenario and now it takes into account all the values as if there was a List addition. But, eventhough that might be true, I prefer what @MultiTech_Visions points out about reliability. If it works now, It may not in the future, so adding SPLIT() and CONCATENATE() might be redundant, it works

Sure! But I recommend using sparingly! These are expensive operations and can cause sluggish performance if the lists become long and used frequently.

This is new(-ish?). It certainly didnโ€™t used to work this way!

Try:

in([linkLocalidad], Split(Concatenate(currentUser[localCSV]), " , "))


@Hamlet your original formula would only pull the first value from the Current_Userโ€™s [LocalCSV] column.

If you had, for example: {1, 2, 3, 4} in that list, your original formula (using index) might be pulling the first number, not the list-of-a-list

  • Sometimes things process differently on the device than they do in the editor
    • Maybe on the device, the list-of-a-list is being converted automatically - and that โ€˜automaticโ€™ action is getting in the wayโ€ฆ maybe. I dunno.

Try wrapping your list-of-a-list inside a concatenate() and see if that helps.

in([linkLocalidad], Split(Concatenate(currentUser[localCSV]), " , "))

This did it!! I guess thereโ€™s something going on with how the App works out the expression on the device.

Thank you to all that stopped by.

Now it works perfecto on editor test and app:

Steve
Platinum 4
Platinum 4

For reference:

So, I discovered a weird oddity/bug today that has to do with some things discussed here.

Assuming the question is โ€œhow do I compare a value against a List of Listsโ€, and we have a Table โ€œtableโ€ with a List type column โ€œlist_colโ€, do we use:

  1. IN( [value] , table[list_col] )

or:

  1. IN( [value] , SPLIT(TEXT( table[list_col] ) , " , " ) )

Iโ€™m quite sure that #1 did NOT work in the past, and you had to use #2. However it does seem that #1 works today, at least in most cases.

What I found today was a complex edge-case where #1 was still not working. Iโ€™m far too tired right now to explain in more detail, but for now just take this as my recommendation to:

Always use #2.

Same.

3X_c_b_cb1caab7cc44788b79f32a3aa001f7abc00d5833.png

Nice.

But, why not retain the standard space-comma-space delimiter, " , " ?

I have no idea, actually. I just documented the observed behavior.

Top Labels in this Space