INTERACT FORUM
More => Old Versions => JRiver Media Center 18 for Windows => Topic started 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!
-
Create the field as a calculated field using:
Regex([genre], /#([^(/>]+)[(/]#/, 1)
-
Thanks!
What code to add if I not only want to test for '/' but also for the '>' character, i.e. an or condition?
-
Added in Red above. You can add additional characters to test for inside the [ ] brackets.
-
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.
-
My fault, sorry. I gave this expression to you too quickly. Here you go:
Regex([genre], /#([^(/>]+)[(/>]#/, 1)
-
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?
-
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).
-
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?
-
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])
-
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?
-
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.
-
Thanks! However, this expression:
if(Regex(IsEqual([genre], Soul//, 8)[genre], /#^0([^(/>]+)[(/>]#/, 0), [R1], [genre])
copies the whole value from Genre if Genre contains 'Soul'.
This expression:
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:
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.
-
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.
-
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!
-
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.
-
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!
-
Gottcha.
This should be easy enough to follow:
if(
regex([genre], /#^(Soul/R'n'B|Classical/Opera|(?:[^(/>]+))#/),
[R1], [genre]
)
-
That did the trick!
Thank you very much!