{expression} help

All about user-defined episode / movie / file name format expressions
UKenGB
Posts: 49
Joined: 04 Jan 2017, 09:26

{expression} help

Post by UKenGB »

I want to be able to add some text plus a tag's content, if the tag exists. Currently, this seems to work:-

Code: Select all

{media.Keyword == null ? "" : " - " + media.Keyword}
But is there a better/more succinct way to achieve this?
User avatar
rednoah
The Source
Posts: 22923
Joined: 16 Nov 2011, 08:59
Location: Taipei
Contact:

Re: Learn how {expressions} work and useful Helper Functions

Post by rednoah »

The + operator works for null values, but String.concat(...) will throw an NPE so we can make use of that behaviour.

e.g. Result

Code: Select all

{' - '.concat('FileBot')}
e.g. Exception => No Result

Code: Select all

{' - '.concat(null)}
Checking the value first is perfectly fine though. Makes the code more readable:

Code: Select all

{if (media.title) ' - ' + media.title}
:idea: Please read the FAQ and How to Request Help.
ChefGregS
Posts: 99
Joined: 30 Mar 2016, 11:14

Re: Learn how {expressions} work and useful Helper Functions

Post by ChefGregS »

I've been studying the various threads with expressions and other people's code and learning a lot. The code you gave me for my folder issue makes total sense and I understand what each part does. So while using this:

Code: Select all

{vf == /2160p/ ? 'Movies 4K' : 'Movies'}
What if I wish to check multiple resolutions and get multiple folders based on them? For example, as above it checks for a resolution of 2160 and if it is puts the file in the Movies 4K folder. If not uses the Movies folder. Now, in my case, I then create a MOVIE named folder under one of those 2 folders. UNLESS the movie is less than 720p. Any movie less than 720p goes into the Movies folder but not in its own named folder.

Example:

Movies\
Movie A (1974)\Movie A [1974, R, 128 Min][1080p 2ch].mp4
Movie B (2010)\Movie B [2010, NA, 93 Min][720p 6ch].avi
Movie C (1983)\Movie C [1983, PG, 118 Min][1080p 6ch].mkv
Movie D [2015, R, 122 Min][540p 2ch].avi
Movie E [1987, PG-13, 98 Min][480p 2ch].mkv

My current code is this:

Code: Select all

M:/{vf == /2160p/ ? 'Movies 4K' : 'Movies'}/{n.upperInitial().colon(' -').replace('?', '!')} ({y})/
What I have been doing is removing this: /{n.upperInitial().colon(' -').replace('?', '!')} ({y})/
when I have a movie that is NOT HD. I know what I want to do..in basic it would be:

If vf<720 then don't create the named folder else do create it. I just have not found the way to do < or <> functions. Maybe it's that simple but if so, I have not gotten them to work currently.
User avatar
rednoah
The Source
Posts: 22923
Joined: 16 Nov 2011, 08:59
Location: Taipei
Contact:

Re: Learn how {expressions} work and useful Helper Functions

Post by rednoah »

I recommend doing this:

Code: Select all

vf == /2160p/ ? 'Movies 4K' : vf == /1080p|720p/ ? 'Movies HD' : 'Movies'
You can do height > 2160 or height < 720 but you will find that many 720p movies that would be considered 720p actually have a height of much less than 720 lines because of some kind of wide screen format.

Using <> is not good for {vf} because {vf} will give you a String value, while {height} will give you an Integer value. String values are ordered alphabetically (i.e. 720p being greater than 1080p because 7 is greater than 1) while Integer values are ordered by their Integer value.
:idea: Please read the FAQ and How to Request Help.
ChefGregS
Posts: 99
Joined: 30 Mar 2016, 11:14

Re: Learn how {expressions} work and useful Helper Functions

Post by ChefGregS »

Ahh..thanks as always.. That makes sense with the <> info.. And yes, I know the issue with 720 movies.. irritates the heck out of me and some I end up re-encoding myself to fix those issues.

I keep forgetting that I can have more than one file folder associated with a Library. I didn't want to add an HD directory..but since it won't affect the LIBRARY I will. Thanks again!!!

You definitely deserve the review / rating I gave you on the MS store!!! :)
User avatar
rednoah
The Source
Posts: 22923
Joined: 16 Nov 2011, 08:59
Location: Taipei
Contact:

Re: Learn how {expressions} work and useful Helper Functions

Post by rednoah »

These kinds of reviews make it worth it. :)
:idea: Please read the FAQ and How to Request Help.
ChefGregS
Posts: 99
Joined: 30 Mar 2016, 11:14

Re: Learn how {expressions} work and useful Helper Functions

Post by ChefGregS »

Hey, just a heads up, this didn't work:

Code: Select all

{vf == /2160p/ ? 'Movies 4K' : vf == /1080p|720p/ ? 'Movies HD' : 'Movies'}
But, I simply did this:

Code: Select all

{vf == /2160p/ ? 'Movies 4K' : vf == /720p/ ? 'Movies HD' : vf == /1080p/ ? 'Movies HD' : 'Movies'}
and it works beautifully!

I'm guessing the | is the same as OR. But I tried it several ways and it simply ran through to Movies. My change, at least, made it work.
User avatar
rednoah
The Source
Posts: 22923
Joined: 16 Nov 2011, 08:59
Location: Taipei
Contact:

Re: Learn how {expressions} work and useful Helper Functions

Post by rednoah »

Sorry, my bad, typo.

Code: Select all

== ... equals
=~ ... matches
e.g.

Code: Select all

{vf == /2160p/ ? 'Movies 4K' : vf =~ /1080p|720p/ ? 'Movies HD' : 'Movies'}
:idea: Please read the FAQ and How to Request Help.
ChefGregS
Posts: 99
Joined: 30 Mar 2016, 11:14

Re: Learn how {expressions} work and useful Helper Functions

Post by ChefGregS »

rednoah wrote: 13 Mar 2018, 17:44 Sorry, my bad, typo.

Code: Select all

== ... equals
=~ ... matches
e.g.

Code: Select all

{vf == /2160p/ ? 'Movies 4K' : vf =~ /1080p|720p/ ? 'Movies HD' : 'Movies'}
Yup, thanks..that did the trick.. Nice to know, though, that apparently the logic can just go on and on if need be. :)
ChefGregS
Posts: 99
Joined: 30 Mar 2016, 11:14

Re: Learn how {expressions} work and useful Helper Functions

Post by ChefGregS »

Ok...here is one:

What I want to do: If certification is blank OR is Not Rated then set it as NR else leave it as it is (PG, R, G, etc...)

I currently use this: {self.certification ?: 'NR'} which gives me NR if certification is blank.

I have tried several of the if/then/or ways to get it to also be NR if it returns Not Rated but thus far nothing I have done has worked. If I don't get an error right off it simply leaves it blank. Thought I had a handle on this but apparently not.
User avatar
rednoah
The Source
Posts: 22923
Joined: 16 Nov 2011, 08:59
Location: Taipei
Contact:

Re: Learn how {expressions} work and useful Helper Functions

Post by rednoah »

Try this:

Code: Select all

any{certification}{'Not Rated'}.replace('Not Rated', 'NR')
any{certification}{'Not Rated'} gives you either the certification, if defined, or "Not Rated", and then replace does what replace does. ;)
:idea: Please read the FAQ and How to Request Help.
ChefGregS
Posts: 99
Joined: 30 Mar 2016, 11:14

Re: Learn how {expressions} work and useful Helper Functions

Post by ChefGregS »

rednoah wrote: 14 Mar 2018, 03:30 Try this:

Code: Select all

any{certification}{'Not Rated'}.replace('Not Rated', 'NR')
any{certification}{'Not Rated'} gives you either the certification, if defined, or "Not Rated", and then replace does what replace does. ;)
Ok.. let me expand on this one (sorry, with over 5000 files to rename again I keep finding files with NEW issues.. LOL)

That code worked perfectly. If not blank uses the cert unless the result is Not Rated. If blank makes it Not Rated. Then IF it is Not Rated changes it to NR. But, how do I now make it replace multiple things? What is the code for replacing Not Rated or N A or Approved.

I'm finally starting to get a grasp on these. I learn by examples. Not just showing them, but as you have been doing, show the code, then explain what it does. THAT's how I learned to program in basic, c, and assembler back in the 80's. The books I used showed code then what that code did AND why. So again, thanks for all the help and for how you give it!
User avatar
rednoah
The Source
Posts: 22923
Joined: 16 Nov 2011, 08:59
Location: Taipei
Contact:

Re: Learn how {expressions} work and useful Helper Functions

Post by rednoah »

e.g.

Code: Select all

any{certification}{'Not Rated'}.replace('Not Rated', 'NR').replace('Not Approved', 'NA')

If you have a lot of replacement / lookup logic, then you can use external CSV files for those mappings, akin to Example 4 here:
viewtopic.php?f=5&t=182


You could also try something more general, like just removing all the lower-case letters and spaces, which leaves you with just the capital initial letters. It'll at least work with the examples you have provided so far. :lol:

Code: Select all

any{certification}{'Not Rated'}.replaceAll(/[ a-z]/)
:idea: Please read the FAQ and How to Request Help.
ChefGregS
Posts: 99
Joined: 30 Mar 2016, 11:14

Re: Learn how {expressions} work and useful Helper Functions

Post by ChefGregS »

rednoah wrote: 14 Mar 2018, 05:18
If you have a lot of replacement / lookup logic, then you can use external CSV files for those mappings, akin to Example 4 here:
viewtopic.php?f=5&t=182
I like this idea. Where can I get more information on how to set up the csv file as well as correctly inserting that code into my code.
User avatar
rednoah
The Source
Posts: 22923
Joined: 16 Nov 2011, 08:59
Location: Taipei
Contact:

Re: Learn how {expressions} work and useful Helper Functions

Post by rednoah »

rednoah wrote: 15 Jul 2012, 09:03 4. Mappings from a CSV file

Code: Select all

{csv('/path/to/names.csv').get(n) ?: n}
e.g. /path/to/names.csv

Code: Select all

Deep Space 9;DS9
How I Met Your Mother;HIMYM
This is the complete example. What exactly is unclear?
:idea: Please read the FAQ and How to Request Help.
ChefGregS
Posts: 99
Joined: 30 Mar 2016, 11:14

Re: Learn how {expressions} work and useful Helper Functions

Post by ChefGregS »

rednoah wrote: 14 Mar 2018, 18:36
rednoah wrote: 15 Jul 2012, 09:03 4. Mappings from a CSV file

Code: Select all

{csv('/path/to/names.csv').get(n) ?: n}
e.g. /path/to/names.csv

Code: Select all

Deep Space 9;DS9
How I Met Your Mother;HIMYM
This is the complete example. What exactly is unclear?
I am doing it exactly as shown but it is doing something very strange. Here is a screenshot:

Image

Notice the code is placed in the right spot and correct. My csv file currently contains the following:

Not Rated;NR
APPROVED;NR
N A;NR
N R;NR

Yet, notice what happened in the position where NR should be in the sample file (between the year and running time.)

It does dawn on me I am missing something.. I tried this: {certification.csv('M:/replacecert.csv').get(n) ?: n} but it just gave a NULL fill: [2017,, 83 MIn] so I am not sure what I am supposed to do. Trying other things and thus far nothing is working.
User avatar
rednoah
The Source
Posts: 22923
Joined: 16 Nov 2011, 08:59
Location: Taipei
Contact:

Re: Learn how {expressions} work and useful Helper Functions

Post by rednoah »

For testing, use only the {...} expression you wanna test, so the last error message is the one you wanna see.

csv(...) will give you a Map that maps keys (Column 1) to values (Column 2). You're using the series name {n} as key which obviously can't work when you want to use the certification as key. So you need to adapt the example to your use case. ;)


Try this things (and nothing else) to understand the format step by step:

Code: Select all

csv('/path/to/names.csv')

Code: Select all

def m = csv('/path/to/names.csv'); m.get('Not Rated')

Code: Select all

csv('/path/to/names.csv').get(certification)

Code: Select all

any{csv('/path/to/names.csv').get(certification)}{"Unkown Certification: $certification"}
:idea: Please read the FAQ and How to Request Help.
ChefGregS
Posts: 99
Joined: 30 Mar 2016, 11:14

Re: Learn how {expressions} work and useful Helper Functions

Post by ChefGregS »

For whatever reason....THIS particular code is just not sinking in.. I am totally lost on this one.. Probably over thinking it...but just not getting it. UGH! I'm missing something when I am trying to use it, I am sure...just not sure what it is I'm missing.
User avatar
rednoah
The Source
Posts: 22923
Joined: 16 Nov 2011, 08:59
Location: Taipei
Contact:

Re: Learn how {expressions} work and useful Helper Functions

Post by rednoah »

What aspect is not clear? You just need to understand the concept of a key/value map:

Code: Select all

def m = [A: 'X', B:'Y']

Code: Select all

def m = [A: 'X', B:'Y']
m.get('A') // yield X
m.get('BAD KEY') // yield null
You can also just copy the last example above and be done with it. It'll do what you want it to do and cover all exceptional cases. ;)
:idea: Please read the FAQ and How to Request Help.
ChefGregS
Posts: 99
Joined: 30 Mar 2016, 11:14

Re: Learn how {expressions} work and useful Helper Functions

Post by ChefGregS »

As I look at this one...I understand what it is doing...

any{csv('/path/to/names.csv').get(certification)}{"Unkown Certification: $certification"}

Where I am confused is that as it seems to me (and you verified) that this will do what I need it to do, it simply isn't. So, as I am testing, I feel like I am missing something. I have put it in my code several ways, and yes, alone to test....and it does nothing...

Here is my edit window, results window, and my csv file. I did remove the text part as it was adding it and I don't want it. (Unknown Certification:) As for the ERROR of Pattern not found...I have no clue why that appears. It has done so in the past but as I change things it comes and goes. It's the one error I don't get because the file it is reading as an example file IS there. The only thing I figure is that because it HAS the NR already in it, it's throwing an error. But, it doesn't seem to have any effect on the actual formatting or example (seen above it.)

Image

Good thing I shave my head...cause I would be pulling my hair out on this one. LOL (sorry for being such a pain about this one...TRYING my best to get it..and I am sure (hope) that it's just something very simple I am doing wrong.)
User avatar
rednoah
The Source
Posts: 22923
Joined: 16 Nov 2011, 08:59
Location: Taipei
Contact:

Re: Learn how {expressions} work and useful Helper Functions

Post by rednoah »

For debugging, please use this format expression (and nothing else!) and then try again:

Code: Select all

{ any{csv('/path/to/names.csv').get(certification)}{"Unkown Certification: $certification"}{"No Certification"} }

:idea: Your large format has a fn.match towards the end which fails intentionally and hides potentially useful warning messages that can tell us why the certification expression isn't working. Test expressions piece by piece, and only integrate pieces you know to be working into your larger format. Same applies to any any{...}{...}{...} sub expression, because any(...) (by design) gobbles up errors.


:arrow: The first step of debugging is to use just this expression, and only this part, to see what happens, to ensure that FileBot can read the file and give you a Map object:

Code: Select all

{ csv('/path/to/names.csv') }


EDIT:

I search for that movie and opened the Format Editor with that, and it turns out that this is a rare case where {certification} is undefined (i.e. it isn't anything) and the original example didn't have a 3rd any{...} clause with a simple default value to take care of that corner case.

Code: Select all

{certification}

Code: Select all

Binding "certification": undefined
:idea: A systematic approach to debugging yields results. Randomly trying things rarely does. ;)
:idea: Please read the FAQ and How to Request Help.
ChefGregS
Posts: 99
Joined: 30 Mar 2016, 11:14

Re: Learn how {expressions} work and useful Helper Functions

Post by ChefGregS »

Ok... when I use the format by itself, It sees the file fine. I get this result:

Code: Select all

{Not Rated=NR, APPROVED=NR, N A=NR, N R=NR, =NR}
BTW: I have MANY movies that return undefined certification.. MOSTLY TV movies
User avatar
rednoah
The Source
Posts: 22923
Joined: 16 Nov 2011, 08:59
Location: Taipei
Contact:

Re: Learn how {expressions} work and useful Helper Functions

Post by rednoah »

I see, that would explain why it worked for me. I haven't tested this with any TV movies (i.e. less popular and more missing data).

This expression fails if certification is undefined:

Code: Select all

{"Unkown Certification: $certification"}
The solution is to have a 3rd fallback that is fail-safe:

Code: Select all

{ any{csv('/path/to/names.csv').get(certification)}{"Unkown Certification: $certification"}{"No Certification"} }
:idea: Please read the FAQ and How to Request Help.
ChefGregS
Posts: 99
Joined: 30 Mar 2016, 11:14

Re: Learn how {expressions} work and useful Helper Functions

Post by ChefGregS »

Code: Select all

{ any{csv('/path/to/names.csv').get(certification)}{"Unkown Certification: $certification"}{"No Certification"} }
This code worked perfectly when inserted into my code.. (just a heads up...the correct spelling is Unknown.) :)
User avatar
rednoah
The Source
Posts: 22923
Joined: 16 Nov 2011, 08:59
Location: Taipei
Contact:

Re: Learn how {expressions} work and useful Helper Functions

Post by rednoah »

I stand corrected. There goes my god complex... :lol:
:idea: Please read the FAQ and How to Request Help.
Post Reply