INTERACT FORUM

More => Old Versions => JRiver Media Center 18 for Windows => Topic started by: Humbledore on March 26, 2013, 02:32:40 am

Title: Create a custom field based on Genre
Post by: Humbledore on March 26, 2013, 02:32:40 am
Hi,
is there a way to create a custom field, in this case called Main Genre based on the content of Genre with the following criteria:
a substring from Genre starting at the first position ending at the position that is found before the character '/' or '>' is found.
For example; if Genre is 'Rock/Indie' I want the value 'Rock' in the new Main Genre field.
Thanks!
Title: Re: Create a custom field based on Genre
Post by: MrC on March 26, 2013, 04:55:07 am
Create the field as a calculated field using:

    Regex([genre], /#([^(/>]+)[(/]#/, 1)
Title: Re: Create a custom field based on Genre
Post by: Humbledore on March 27, 2013, 03:05:15 am
Thanks!
What code to add if I not only want to test for '/' but also for the '>' character, i.e. an or condition?
Title: Re: Create a custom field based on Genre
Post by: MrC on March 27, 2013, 11:17:05 am
Added in Red above.  You can add additional characters to test for inside the [ ] brackets.
Title: Re: Create a custom field based on Genre
Post by: Humbledore on March 27, 2013, 09:29:29 pm
Unfortunately this expression pick the value AFTER the '>' character. I want the value BEFORE '>'.
When testing for '/', however, it still pick the correct value, before the '/' character.
Title: Re: Create a custom field based on Genre
Post by: MrC on March 27, 2013, 10:58:14 pm
My fault, sorry.  I gave this expression to you too quickly.  Here you go:

    Regex([genre], /#([^(/>]+)[(/>]#/, 1)
Title: Re: Create a custom field based on Genre
Post by: Humbledore on March 28, 2013, 02:07:11 am
Thanks, now it looks as expected!
Now I wonder (since these expressions are not that straightforward and logically understandable for a novice like me); is it somewhere possible to learn more about how to deal and handle this kind of quirky code?
Title: Re: Create a custom field based on Genre
Post by: MrC on March 28, 2013, 05:35:36 am
Regex() uses the relatively simple language of Regular Expressions.  It looks confusing, just like another written language looks confusing until you learn its alphabet.

The RE looked for any number of characters that are not ( / or >.   And it remember those that matched.  Then it looked for one character that was a ( / or >.

And the MC Regex() expression output that remembered value.

Expressions are listed here:

   http://wiki.jriver.com/index.php/Media_Center_expression_language (http://wiki.jriver.com/index.php/Media_Center_expression_language)

There are plenty of good RE tutorials or overviews available on the web.  I've posted many here on the forum (use the forums advanced search, search for Regex with author MrC).
Title: Re: Create a custom field based on Genre
Post by: Humbledore on March 30, 2013, 01:49:19 am
Thanks!
I wrapped the RE in an if() function in order to create a value when Genre doesn't contain '/' or '>'. For the if condition I just changed the RE mode to 0 but kept rest of the expression. I guess you can shortened the RE when using mode 0 because there is no need to create any string output value, or?   
Title: Re: Create a custom field based on Genre
Post by: MrC on March 30, 2013, 02:31:39 am
You'll still want the same RE, but use mode 0 to test.  Then, [R1] will contain the captured main genre, which you can use later in the remainder of the expression:

    if(Regex([genre], /#([^(/>]+)[(/>]#/, 0), [R1], [genre])
Title: Re: Create a custom field based on Genre
Post by: Humbledore on March 30, 2013, 07:18:51 am
Even better... Thanks!
Finally, I want to add one or two exceptions:
For example, if Genre starts with 'Soul/R'n'B' I want that string to become the Main Genre. Can I accomplish this within the same Regex or is it smoother to use an additional function, maybe the IfElse() function? 
Title: Re: Create a custom field based on Genre
Post by: MrC on March 30, 2013, 11:46:03 am
With other regular expression implementations (i.e. not Microsoft's), you can use what is called Negative Lookbehind to solve this using RE.  But we can't do that here.

So, instead, you could use nested If() or IfElse() statements with IsEqual(), to first test the value of [genre] for Soul/R'n'B.  But that is clumsy.  So let's use the fact that IsEqual() returns a 0 or 1 value, and by tacking that in front of Genre, we can use the same RE with a minor adjustment:

if(Regex(isequal([genre], Soul//, 7)[genre], /#^0([^(/>]+)[(/>]#/), [R1], [genre])

Whenever your string doesn't match (i.e. you want to split the genre), this expressions places a 0 before the [genre] value that Regex() sees, and the RE matches and captures only the first portion of genre (and not the 0).  Otherwise, a 1 is appended, and the RE won't match, so whole [genre] is output.

If you want to match more patterns to exclude, we can use Regex inside:

if(Regex(regex([genre], /#(?:Soul/R'n'B|Classical/Opera)#/)[genre], /#^0([^(/>]+)[(/>]#/, 0), [R1], [genre])

Your strings are separated by the alternation | symbol in the RE.  Now you can add more exceptions easily.
Title: Re: Create a custom field based on Genre
Post by: Humbledore on March 31, 2013, 12:35:13 am
Thanks! However, this expression:
Code: [Select]
if(Regex(IsEqual([genre], Soul//, 8)[genre], /#^0([^(/>]+)[(/>]#/, 0), [R1], [genre])copies the whole value from Genre if Genre contains 'Soul'.

This expression:
Code: [Select]
if(Regex(IsEqual([genre], Soul/R'n'B, 8)[genre], /#^0([^(/>]+)[(/>]#/, 0), [R1], [genre])creates the value 'Soul' if Genre starts with 'Soul/R'n'B'.

And this:
Code: [Select]
if(Regex(regex([genre], /#(?:Soul/R'n'B|Classical/Opera)#/)[genre], /#^0([^(/>]+)[(/>]#/, 0), [R1], [genre])doesn't make any change at all, just copies the whole value from Genre.
Title: Re: Create a custom field based on Genre
Post by: MrC on March 31, 2013, 01:09:03 pm
I made some adjustments above for clarity.

I hadn't thought you would have various Soul//xxx values, so yes, you need to use the entire string then for an exception (or at least as much as necessary to unambiguously match).  Also, you want to use an extra / to escape the /, since that is MC's quote character.  Although it works in this case, its good practice to use it.

if(Regex(isequal([genre], Soul//R'n'B, 7)[genre], /#^0([^(/>]+)[(/>]#/), [R1], [genre])

The last expression does work.  See attached.
Title: Re: Create a custom field based on Genre
Post by: Humbledore on March 31, 2013, 11:51:23 pm
Maybe I do something wrong but

if(Regex(isequal([genre], Soul//R'n'B, 7)[genre], /#^0([^(/>]+)[(/>]#/), [R1], [genre])

doesn't change anything when Genre contains 'Soul/R'n'B', see RE1 attached.

And

if(Regex(regex([genre], /#(?:Soul/R'n'B|Classical/Opera)#/)[genre], /#^0([^(/>]+)[(/>]#/, 0), [R1], [genre])

also doesn't change anything when Genre contains 'Soul/R'n'B', see RE2 attached.

Note that I only want genres that STARTS with Soul/R'n'B to be selected for the Soul/R'n'B main genre.
Thanks!
Title: Re: Create a custom field based on Genre
Post by: MrC on April 01, 2013, 12:54:30 am
I think we're having a miscommunication, and it feels like your goals are changing.

Give me several simple examples of main genres that should and should not change, and their results.  The data in the screenshots is the right idea.
Title: Re: Create a custom field based on Genre
Post by: Humbledore on April 02, 2013, 03:40:04 am
No, my goals are not changing. But I apologize for any misunderstanding. My native language is not English so maybe some inappropriate words can become confusing, sorry for that.

Anyway, here are the main rules again and some examples that hopefully makes everything clear:

...is there a way to create a custom field, in this case called Main Genre based on the content of Genre with the following criteria:
a substring from Genre starting at the first position ending at the position that is found before the character '/' or '>' is found.
For example; if Genre is 'Rock/Indie' I want the value 'Rock' in the new Main Genre field.

...I want to add one or two exceptions:
For example, if Genre starts with 'Soul/R'n'B' I want that string ('Soul/R'n'B') to become the Main Genre.

Genre                              Main Genre
House/Techno                  House
Pop>Synth                       Pop
Soul/Funk                        Soul
Funk/Soul/R'n'B                Funk
Funk>Disco/Soul/R'n'B      Funk
Soul/R'n'B                        Soul/R'n'B (exception)
Soul/R'n'B/Hip Hop>Rap    Soul/R'n'B (exception)

Thanks!
Title: Re: Create a custom field based on Genre
Post by: MrC on April 02, 2013, 11:51:29 am
Gottcha.

This should be easy enough to follow:

if(
   regex([genre], /#^(Soul/R'n'B|Classical/Opera|(?:[^(/>]+))#/),
   [R1], [genre]
)
Title: Re: Create a custom field based on Genre
Post by: Humbledore on April 03, 2013, 01:39:17 am
That did the trick!
Thank you very much!