Having a brainfart moment. (Get key from array match.)

Any questions? Need some help?
Post Reply
User avatar
Wolfie
Posts: 144
Joined: 27 Oct 2015, 02:59

Having a brainfart moment. (Get key from array match.)

Post by Wolfie »

Episodes (not movies).

Want to use an array (simple example):

Groovy: Select all

franchise = [
	"StarTrek" = "Star ?Trek",
	"StarWars" = "Star ?Wars|(The ?)?Mandelorian|Obi-?Wan ?Kenobi",
],
When looking at the title of the file, return the key of the value that matches (if any).

Goal is to allow put grouped shows into a folder other than the default TV shows folder. If there's no match, then the default will be used. That's not a problem (the 'any' feature is wonderful).

So what am I forgetting about here Noah? I'm sure I'll be doing a V8 retro reaction, unless it's a function that I haven't seen/used before.
Last edited by Wolfie on 16 Aug 2025, 02:01, edited 1 time in total.
User avatar
Wolfie
Posts: 144
Joined: 27 Oct 2015, 02:59

Re: Having a brainfart moment. (Get key from array match.)

Post by Wolfie »

Nevermind. 🤦‍♂️

Decided to actually try using Google and found the answer.

Groovy: Select all

return franchise.find{k,v-> fn=~v }.key
At least I hope that's right.
User avatar
rednoah
The Source
Posts: 24099
Joined: 16 Nov 2011, 08:59
Location: Taipei
Contact:

Re: Having a brainfart moment. (Get key from array match.)

Post by rednoah »

Yep, that's how I'd do it. If you can't just do a lookup-by-key then you'll have to loop through the map and until you find the entry that matches your conditions.



EDIT:

The match() helper might just do what you need though:

Groovy: Select all

az.match('[a-f]': '/volume1', '[g-x]': '/volume2') ?: '/volume3'
:idea: Please read the FAQ and How to Request Help.
User avatar
Wolfie
Posts: 144
Joined: 27 Oct 2015, 02:59

Re: Having a brainfart moment. (Get key from array match.)

Post by Wolfie »

Here's some code and data that I hope will help others.

Groovy: Select all

	def root="P:"
	config="P:/FileBot/"
	
	def maps = include config+"config.groovy"
	def map = maps['DEFAULTS'] + maps['TV'], folders=map['folders'], dd=map['dd'], talkshows=map['talkshows'], anime=(anime ? (map['anime'] ? "ANIME" : null) :null)
	def groups = allOf{"TV"}{map['groups'].join('|')}{anime}.join('|'), drives=folders.keySet().join('|')
	def franchises = map['franchises'], franchise = any{franchises.find{k,v-> fn=~v }.key}{franchises.find{k,v-> imdbid=~"^${v}\$" }.key}{franchises.find{k,v-> tvdbid=~"^${v}\$" }.key}{}
	def col = /(tt|tmdb|tvdb)[0-9]+/

Groovy: Select all

[
	"DEFAULTS":[
		"dd":"06",
		"collections":"collections.txt",
		"overrides":"overrides.txt",
		"folders":[
			"01":"_01",
			"02":"_02",
			"03":"_03",
			"04":"_04",
			"05":"_05",
			"06":"_06",
			"E1":"_E1",
			"E2":"_E2",
			"E3":"_E3",
		],
	],

	"TV":[
		"talkshows":true,
		"anime":false,
		"franchises":[
			"StarTrek": "^Star ?Trek|tt0112178|74550",
			"StarWars": "^(Star ?Wars|(The ?)?Mandelorian|Obi-?Wan ?Kenobi)",
		],
		"groups":[
			"DC(shows)?",
			"Marvel(TV)?",
			"Star ?Trek",
		],
	],

	"MOVIES":[
		"collectionsFolder":"_",
	]
]
The "franchises" here is the most recent thing I worked on. Idea is to let it override the default folder name of "TV" later on using the any{} function.

As an example...

Groovy: Select all

TVfolder=any{franchise}{anime}{"TV"}
So if someone wants to group a bunch of related shows into the same main folder, they just name to set the name of the folder as the key (left side), then enter either names or IMDB ID's or TVDB ID's (or a mix) separated by |'s. If using names, regex format. The key can have spaces, of course, even though I don't include them above. The 'talkshows' value is since I also separate talk shows from regular shows. I prefer to not separate shows based on anime, but that's made into an easy to toggle option. Helpful when wanting to toggle something both via GUI and command line uses without making changes in multiple places.
User avatar
Wolfie
Posts: 144
Joined: 27 Oct 2015, 02:59

Re: Having a brainfart moment. (Get key from array match.)

Post by Wolfie »

Now here's an interesting situation that is baffling me.

Using the 'folders' array from above ("01" = "_01", etc), I'm able to get results from one method but not another.

Working:

Groovy: Select all

folders[file.path.match("(?<=\\_)(${folders.keySet().join('|')})")]
Not working:

Groovy: Select all

folders[file.path.match("(?<=\\)(${folders.values().join('|')})")]
The ONLY difference between the two is that the first turns into "(?<=\\_?)(01|02|03|04|05|06|E1|E2|E3)\\" and the second turns into "(?<=\\)(_01|_02|_03|_04|_05|_06|_E1|_E2|_E3)" but yet only the first works even though both searches should return the same result.

Example path: "A:/_02/TV/BCDEFG"

Both should be returning "_02" but the second doesn't return anything. Does having "_" in front of them somehow mess up the regex engine?
User avatar
rednoah
The Source
Posts: 24099
Joined: 16 Nov 2011, 08:59
Location: Taipei
Contact:

Re: Having a brainfart moment. (Get key from array match.)

Post by rednoah »

:?: What are the values that are being worked with? What is file.path? What is the pattern you pass to the match() function?

:idea: Plugging in the values you shared we get a regular expression error:

Format: Select all

{ 'A:/_02/TV/BCDEFG'.match("(?<=\\)(_01|_02|_03|_04|_05|_06|_E1|_E2|_E3)") }

Code: Select all

Expression yields empty value: Unclosed group near index 43
(?<=\)(_01|_02|_03|_04|_05|_06|_E1|_E2|_E3)
:?: What does (?<=\\) try to do? In this case it's actually escaping the ) parenthesis. The first \ is for escaping the \ in the String literal.


:idea: Since _ doesn't need to be escaped, the \\ in (?<=\\_) does nothing. It could just be (?<=_). If wanted to not have a lookbehind you would remove that construct altogethere instead of just removing the _ character.


:arrow: tl;dr you probably meant to do just this:

Groovy: Select all

folders[ file.path.match( folders.values().join('|') ) ]
:idea: Please read the FAQ and How to Request Help.
User avatar
Wolfie
Posts: 144
Joined: 27 Oct 2015, 02:59

Re: Having a brainfart moment. (Get key from array match.)

Post by Wolfie »

I'm trying to get it to match the '/' in "A:/" to limit it to a single folder name. Trying to make sure it matches the "_02" in "/_02/" and not in a situation like "part_023" for example.
User avatar
rednoah
The Source
Posts: 24099
Joined: 16 Nov 2011, 08:59
Location: Taipei
Contact:

Re: Having a brainfart moment. (Get key from array match.)

Post by rednoah »

{ file.path } will be using \ and not / on Windows. In the context of a file path /\ doesn't matter, but in the context of a regular expression one does no match the other.


:!: The preview in the format editor will display the normalised file path. Meaning it'll display / even if the file path actually uses \ in the variable value.


:arrow: I'd write a pattern that matches either / or \ to ensure it works on all platforms and more importantly avoid issues where the \ is displayed as / leading to confusion:

Format: Select all

{ 'A:\\_02\\test.txt'.match(/(?<=\\|\/)(_02)(?=\\|\/)/) }
:idea: Please read the FAQ and How to Request Help.
User avatar
Wolfie
Posts: 144
Joined: 27 Oct 2015, 02:59

Re: Having a brainfart moment. (Get key from array match.)

Post by Wolfie »

Here's one for you. How do I do something like this:

Groovy: Select all

array.find{ k,v -> v.find{ p,regex -> value=~regex} }
Imagine an array like:

Groovy: Select all

"arrayT":[
	"a1":[ "a11":"regex11", "a12":"regex12", ],
	"a2":[ "a21":"regex21", "a22":"regex22", ],
	"a3":[ "a31":"regex31", "a32":"regex32", ],
],
When I try to do it with one .find{}, it returns only the first array (a1) even if the match is in (a2). :?:
User avatar
rednoah
The Source
Posts: 24099
Joined: 16 Nov 2011, 08:59
Location: Taipei
Contact:

Re: Having a brainfart moment. (Get key from array match.)

Post by rednoah »

e.g.

Groovy: Select all

{
	def data = [
		"arrayT":[
			"a1":[ "a11":"regex11", "a12":"regex12", ],
			"a2":[ "a21":"regex21", "a22":"regex22", ],
			"a3":[ "a31":"regex31", "a32":"regex32", ],
		],
	]
	
	def value = /regex32/

	data.arrayT.findResult{ k1, v1 ->
		v1.findResult{ k2, v2 ->
			if (value =~ v2) return k1
		}
	}
}

Code: Select all

a3
:idea: Please read the FAQ and How to Request Help.
User avatar
Wolfie
Posts: 144
Joined: 27 Oct 2015, 02:59

Re: Having a brainfart moment. (Get key from array match.)

Post by Wolfie »

Any way to get it to return an array? So that the following is the result...

Code: Select all

result.key = "a3"
result.value = {"a32":"regex32"}
result.value.key = "a32"
result.value.value = "regex32"
User avatar
rednoah
The Source
Posts: 24099
Joined: 16 Nov 2011, 08:59
Location: Taipei
Contact:

Re: Having a brainfart moment. (Get key from array match.)

Post by rednoah »

:arrow: Maybe like this?

Format: Select all

{
	def data = [
		"arrayT":[
			"a1":[ "a11":"regex11", "a12":"regex12", ],
			"a2":[ "a21":"regex21", "a22":"regex22", ],
			"a3":[ "a31":"regex31", "a32":"regex32", ],
		],
	]
	
	def value = /regex32/

	data.arrayT.findResult{ k1, v1 ->
		v1.findResult{ k2, v2 ->
			if (value =~ v2) return [(k1):[(k2):v2]]
		}
	}
}

Code: Select all

{a3={a32=regex32}}


:arrow: I don't see the point of using a map inside a map when you know it'll only have 1 mapping. Maybe you rather mean to do something like this?

Format: Select all

{
	def data = [
		"arrayT":[
			"a1":[ "a11":"regex11", "a12":"regex12", ],
			"a2":[ "a21":"regex21", "a22":"regex22", ],
			"a3":[ "a31":"regex31", "a32":"regex32", ],
		],
	]
	
	def value = /regex32/

	def (k1, k2, v2) = data.arrayT.findResult{ k1, v1 ->
		v1.findResult{ k2, v2 ->
			if (value =~ v2) return [k1, k2, v2]
		}
	}
	
	return "$k1 $k2 $v2"
}

Code: Select all

a3 a32 regex32
:idea: Please read the FAQ and How to Request Help.
User avatar
Wolfie
Posts: 144
Joined: 27 Oct 2015, 02:59

Re: Having a brainfart moment. (Get key from array match.)

Post by Wolfie »

When I try to get it into a variable (not return the result as final), it doesn't want to work for me. ☹

The idea is to get it so that a single variable can be used to either get the "group" it match (a1, a2, a3), the key (a11, a12, etc), or the value (regex32) as desired. It's similar to the above but a step beyond.

Imagine:

Groovy: Select all

"paths":[
	"Star Trek":[
		"/first/path/":"^(first set of matches)",
		"/second/path/:"^(second|set|of|matches)",
	],
	"Star Wars":[
		"/first/path/again":"^(new set of match)",
	],
],
Let's assume that ST TNG matches the second one.
data.key = "Star Trek"
data.value.key = "/second/path/"
data.value.value = "^(second|set|of|matches)"

If I want to have it show me the "data.value.value" as filenames (for debugging/testing purposes, of course), then I can do so easily.
User avatar
rednoah
The Source
Posts: 24099
Joined: 16 Nov 2011, 08:59
Location: Taipei
Contact:

Re: Having a brainfart moment. (Get key from array match.)

Post by rednoah »

Wolfie wrote: Yesterday, 13:06 The idea is to get it so that a single variable can be used to either get the "group" it match (a1, a2, a3), the key (a11, a12, etc), or the value (regex32) as desired.
The second example above will give you what you want as 3 separate variables. If you want it as a single variable that has 2 properties, the second of which itself has 2 properties, then I would ask why make things more difficult? But here you go:

Format: Select all

{
	def data = [
		"paths":[
			"Star Trek":[
				"/first/path/":"^(first set of matches)",
				"/second/path/":"^(second|set|of|matches)",
			],
			"Star Wars":[
				"/first/path/again":"^(new set of match)",
			],
		],
	]
	
	def input = "second.set.of.matches"

	def result = data.paths.findResult{ group, paths ->
		paths.findResult{ path, pattern ->
			if (input =~ pattern) return [key: group, value: [key: path, value: pattern]]
		}
	}
	
	return [result.key, result.value.key, result.value.value].join('/')
}

Code: Select all

Star Trek/second/path/^(second|set|of|matches)

I would find this a bit hard to read though:

Code: Select all

result.key
result.value.key
result.value.value
while well-named variables seem a bit more easy to read:

Code: Select all

group
path
pattern
:idea: Please read the FAQ and How to Request Help.
User avatar
Wolfie
Posts: 144
Joined: 27 Oct 2015, 02:59

Re: Having a brainfart moment. (Get key from array match.)

Post by Wolfie »

Tweaked it to just be variable.(property) instead of branching it. Rethinking the idea though, as I noticed a potential problem, but not giving up on what you taught me. It's quite useful.
User avatar
Wolfie
Posts: 144
Joined: 27 Oct 2015, 02:59

Re: Having a brainfart moment. (Get key from array match.)

Post by Wolfie »

And another tweak to account for the potential problem. So idea is still on. 😁
Post Reply