Jump to content

First Occurrence of Unique Values In A List

Recommended Posts

Posted (edited)

I'm trying to get the first occurrence of each unique value from a returned separated list using the While function.

Can anyone tell me why this calculation doesn't work?

SetRecursion (

While ( [

~values = "Apple¶Apple¶Apple¶Orange¶Orange¶Orange" ;

~prevValue = "" ;

~result = ""

] ;

not IsEmpty ( ~values ) ;

~value = GetValue ( ~values ; 1 ) ;

~result = If ( ~value ≠ ~prevValue ; ~result & "¶" & ~value ) ;

~prevValue = ~value ;

~values = RightValues ( ~values ; ValueCount ( ~values ) - 1 )

] ;

~result

)

; 10 )

I have been staring at this all morning and I just can't see where I'm going wrong.

Any help would be appreciated

Thanks

Edited by Ron Cates
Share on other sites
Posted (edited)

It doesn't work because every time the value repeats, you empty the result. You can verify this by testing with:

`~values = "Apple¶Apple¶Apple¶Orange¶Orange¶Orange¶Plum" ;`

Instead of:

`~result = If ( ~value ≠ ~prevValue ; ~result & "¶" & ~value ) ;`

you should be doing:

`~result = If ( ~value ≠ ~prevValue ; ~result & "¶" & ~value ; ~result ) ;`

or preferably, to avoid a leading carriage return:

`~result = If ( ~value ≠ ~prevValue ; List ( ~result ;  ~value ) ; ~result ) ;`

Edited by comment
• 1
Share on other sites

Ugh! I knew it had to be right in front of me. Thank you so much. Probably staring at it too long and just not seeing my own nose in front of my face.

Thank You

Share on other sites

P.S. It should be noted that this does not "get the first occurrence of each unique value from a returned separated list". It returns a single value for each consecutive run of identical values. If the initial list is:

```Apple
Apple
Apple
Orange
Orange
Orange
Apple
Apple
Orange```

then the result will be:

```Apple
Orange
Apple
Orange```

Not sure why this would be needed.

Share on other sites

It was a starting point. I realized what you just pointed out and adjusted ~prevValue to build a returned separated list of each value that had already been accounted for and used PattenCount to determine if each line contained a previously listed value. I was able to get the result I was looking for which was just the first occurrence of each value. Of course my use case is more complicated than Apple, Apple Apple.  I just simplified the While calculation to define my immediate problem.

Thanks as always for all your help.

Share on other sites
4 minutes ago, Ron Cates said:

adjusted ~prevValue to build a returned separated list of each value that had already been accounted for and used PattenCount to determine if each line contained a previously listed value

1. You should not use PatternCount() to determine the presence of a value in a list; FilterValues() is both simpler and faster.

2. How is this different from the built-in UniqueValues() function?

Share on other sites
Posted (edited)

The actual text is more like

Apple | Some text
Apple | Some more text
Apple | Different text
Orange | Random text
Orange | Still more text
Orange | A Different text

I was looking to get

Apple | Some text
Orange | Random text

I ended up with this:

SetRecursion (

While ( [

~values = "Apple | Some text¶Apple | Some more text¶Apple | Different text¶Orange | Random text¶Orange | Still more text¶Orange | A Different text" ;

~prevValue = "" ;

~result = ""

] ;

not IsEmpty ( ~values ) ;

~string = GetValue ( ~values ; 1 ) ;
~value = GetValue ( Substitute ( ~string ; " | " ; "¶" ) ; 1 ) ;

~result = If ( not PatternCount ( ~prevValue ; ~value & "|" ) ; List ( ~result ; ~string ) ; ~result ) ;

~prevValue =  ~prevValue & ~value & "|" ;

~values = RightValues ( ~values ; ValueCount ( ~values ) - 1 )

] ;

~result

)

; 10 )

Edited by Ron Cates
Share on other sites

I see.

So what is your expected result given a list like:

```Fired | One
Fired | Two
Fired | Three
Red | Four
Red | Five```

Share on other sites

Fired | One
Red | Four

And when I test it I see the issue. Fired and red, both contain "red".

I made some adjustments

While ( [

~values = "Fired | One¶Fired | Two¶Fired | Three¶Red | Four¶Red | Five" ;

~prevValue = "|" ;

~result = ""

] ;

not IsEmpty ( ~values ) ;

~string = GetValue ( ~values ; 1 ) ;
~value = GetValue ( Substitute ( ~string ; " | " ; "¶" ) ; 1 ) ;

~result = If ( not PatternCount ( ~prevValue ; "|" &~value & "|" ) ; List ( ~result ; ~string ) ; ~result ) ;

~prevValue =  ~prevValue & ~value & "|" ;

~values = RightValues ( ~values ; ValueCount ( ~values ) - 1 )

] ;

~result

)

Share on other sites

[shrug]

8 hours ago, comment said:

You should not use PatternCount() to determine the presence of a value in a list; FilterValues() is both simpler and faster.

--
BTW, you haven't given us a clue what this is really about. It seems like the real issue here is lack of separation between two atomic values at the origin - IOW, breaking the "one fact per field" rule - and this elaborate processing is required only as a result.

Share on other sites

Sorry I didn't clarify. It's an interface project. I was working on developing a dynamic menu and navigation system that is driven from the list of layouts and determined by the layout naming convention. The goal was to be able to add layouts without having to update any menus, buttons or navigation scripts. Initially it was just a single menu for small projects but I went a little nuts and developed it out to be a three level navigation system. The whole thing works entirely in the Button Bar calculations. No scripting involved. It worked out quite nicely.

Thanks again

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
• Create New...

Important Information

By using this site, you agree to our Terms of Use.