Return all the index values of a json array that contain a string in a specific key, separated by commas.

Discuss macro implementations, ask for macro help (to share your creations, see User Creations, probably either Campaign Frameworks or Drop-in Resources).

Moderators: dorpond, trevor, Azhrei, giliath, jay, Mr.Ice

Post Reply
Shadow Wizard
Giant
Posts: 192
Joined: Mon Apr 11, 2011 8:11 pm

Return all the index values of a json array that contain a string in a specific key, separated by commas.

Post by Shadow Wizard »

So, I thought I would post a new topic, because I think this will make it easier for others to find (and me) in the future.
I have been working on JSON arrays with the help of a very helpful member (Who wrote part of this code) and so far I have this:

Code: Select all

[h: key="name"]
[H: status = input(
	"value     |        | Equipment to find | TEXT | WIDTH=15"
	)]

[r: indexvalue = replace(json.path.read(myData,strformat("\$[?(@.['%s'] == '%s')]",key,value),"ALWAYS_RETURN_LIST,AS_PATH_LIST,SUPPRESS_EXCEPTIONS"),"[^0-9]","")]
and this code will return all the indexes who's name exactly matches "value" with no separator. For example, if the value is found in index 1 and index 22 it will return "122"
So, I need to make 3 changes. Please, in the interest of me learning from the changes if you don't mind posting the code between each change (if you make the changes for me that is)?
First (Because I think change 3 may be very hard, or it may be very easy) it needs to change so if the key CONTAINS the value to return the index number. For example. lets say the array contains a key with the value "Quarterstaff", if I imputed "Quarter" it would return the index value (I hope thats clear)
Second, It needs to be case insensitive. "Quarterstaff" and "quarterstaff" and "QUARTERSTAFF" need to be all the same.
Finally, (I suspect this will be very easy, or very hard) it needs to separate each index with a , (Well, with anything I would guess, but , is just ideal) so instead of returning "122" it would return "1,22" Even if it end up returning "1,22," it will be fine; I can strip out the last comma myself.
If someone doesn't mind making the changes, that would be amazing as I can learn from studying the differences. Or baring that assisting me to make the changes myself.
A big advance thank you.

Shadow Wizard
Giant
Posts: 192
Joined: Mon Apr 11, 2011 8:11 pm

Re: Return all the index values of a json array that contain a string in a specific key, separated by commas.

Post by Shadow Wizard »

So, its a MESS, but I managed to solve #3, each index is now separated by ","
Basically instead of replacing everything that isn't needed with "", I replaced it with "x"
I then replaced every instance that contains one or more x's with "," (Meaning "x" becomes "," and "xxxxx" also becomes, just a single comma ",")
I then check the front of the variable that contains the list of indexes for a ",", and if the first char is a ",", it removes it.
I then check the last char of the variable, and if it is a "," it removes it.
This leaves a list that contains every index that matches, separated by commas.
myData contains the JSON array..

Code: Select all

[h: indexvalue = replace(json.path.read(myData,strformat("\$[?(@.['%s'] == '%s')]","name","Quarterstaff"),"ALWAYS_RETURN_LIST,AS_PATH_LIST,SUPPRESS_EXCEPTIONS"),"[^0-9]","x")]

[h:newindexvalue = replace(indexvalue,"[x]+",",")]
[h:lengthofstring=length(newindexvalue)]

[h, if(substring(newindexvalue,0,1)==","), CODE:{
[newindexvalue=substring(newindexvalue,1,lengthofstring)]
[lengthofstring=length(newindexvalue)]
};{}]
[h, if(substring(newindexvalue,lengthofstring-1,lengthofstring)==","), CODE:{
[newindexvalue=substring(newindexvalue,0,lengthofstring-1)]
};{}]
[r:newindexvalue]
Only took me about 4 1/2 hours... lol.

User avatar
aliasmask
RPTools Team
Posts: 9029
Joined: Tue Nov 10, 2009 6:11 pm
Location: Bay Area

Re: Return all the index values of a json array that contain a string in a specific key, separated by commas.

Post by aliasmask »

Code: Select all

[H: key="name"]
[H: status = input(
	"value     |        | Equipment to find | TEXT | WIDTH=15"
	)]

[R: paths = json.path.read(data,strformat("\$[?(@.['%s'] =~ /.*%s.*/i)]",key,value),"ALWAYS_RETURN_LIST,AS_PATH_LIST,SUPPRESS_EXCEPTIONS")]
<!-- using =~ allows us to search with regex. the .* means any number of any characters including none. %s is the inserted value. / are the bounds of
      the regex and i means (i)nsensitive case.
   This version instead or returning a single number will return an array of paths. It designed for a "record" structure only, so an array of objects.
   The paths always start with $ then inside the brackets is the index. The easiest way to get the number is to delete everything that's not a number,
      done in loop below.
-->

[H: indexes = ""]
[H, foreach(path,paths): indexes = listAppend(indexes,replace(path,"[^0-9]",""))]

[R: indexes]

Shadow Wizard
Giant
Posts: 192
Joined: Mon Apr 11, 2011 8:11 pm

Re: Return all the index values of a json array that contain a string in a specific key, separated by commas.

Post by Shadow Wizard »

Thank you. A lot better then my mess. I had woke up this morning thinking I could search with regex for #1 and #2, but didn't even think it would have needed to be =~ instead of =
There was a bit of an error in the code. In the loop, you forgot to tell listreplace what list to replace from, making the correction as follows:

Code: Select all

[H, foreach(path,paths): indexes = listAppend(indexes,replace(path,"[^0-9]",""))]
I am beginning to think you do these little things to make sure I am not just looking for you to give me all the answers, so I have to work a bit. :) lol
On the plus size, I have learned =~ allows you to search with regex, and I think I also understand the foreach loop...

Post Reply

Return to “Macros”