Page 1 of 2

Create multidimensional array from string? [SOLVED]

Posted: Fri Jul 09, 2021 9:49 am
by stam
Hi all,
is it possible to describe a multidimensional array in string and then use this to create an array to assign values to?
ie: if a string contains: "["key1"]["key2"]", is it possible to then create an array with these sub-keys and assign a value to ["key2"]?

The use-case i have in mind is for processing a return-delimited list where each line describes different keys & sub-keys of the same array, so would need to automate processing of each line and assign the final item of each line to the last sub-key of that particular branch...

I was thinking maybe processing the text and converting it somehow to JSON and using the JSON functions to convert to array, but the prospect of automating conversion of the text to JSON is at least as complex... I can't see a simpler way of doing this but perhaps you clever guys can!

Many thanks
Stam

Re: Create multidimensional array from string?

Posted: Fri Jul 09, 2021 1:22 pm
by Klaus
Hi Stam,

well, the ITEMDELIMITER is your friend here, so it should not be too difficult to pase these strings.
Maybe you can provide a complete line of data?


Best

Klaus

Re: Create multidimensional array from string?

Posted: Fri Jul 09, 2021 2:31 pm
by dunbarx
Stam.

Assuming you have in a field 1:
dog
cat
mouse
Do you mean something like:

Code: Select all

on mouseUp
   get fld 1
   put line 3 of it into mayArray[line 1 of it][line 2 of it][x]
end mouseUp
Craig

Re: Create multidimensional array from string?

Posted: Fri Jul 09, 2021 5:44 pm
by stam
Not quite... it's a bit more complex than that.

The structure of the free text is a bit like this:

root | key1 | content1
root | key1 | content2
root | key1 | key2 | content3
root | key1 | key2 | content4
root | key3 | content5

the key names are dynamically generated, so can't know in advance the key names.

I can certainly generate the text that would be in the SE for the array, ie for line 3 this would be:
root["key1"]["key2"]["content3"] -- but this is a string, not an array.

I thought that perhaps i could use a do merge() to put a value into the dynamically named array but this doesn't work.
If say we call the above string tArray, and the value to put in the destination key tValue:

Code: Select all

do merge ("put" && quote & tValue & quote && "into" && tArray)   -- where tArray = root["key1"]["key2"]["content3"] 
doesn't produce any output - neither an error nor an array.

With quite a bit of work i could probably manage to automatically convert this to JSON, but because each subkey may or may not be an array that's going to be a pain to code, but would then be easy to convert an array...

the JSON would have to look like this:

Code: Select all

{
	"root" : [
	 {
	 	"key1" : [
	 		{"item" : "content1"},
	 		{"item" : "content2"},
	
	 		{"key2" : [
	 			{"item" : "content3"},
	 			{"item" : "content4"}
	 		]},
	 	]
	 },
         {
               "key3" : [
                                  {"item" : "content5"}
                        ]
         }
	]
}
this isn't critical, but i thought i'd work on problem i saw posted somewhere thinking yeh, this will be easy to convert to an array...... but i'm probably having several senior moments here...

Re: Create multidimensional array from string?

Posted: Fri Jul 09, 2021 6:25 pm
by FourthWorld
Variables can be used as keys.

Re: Create multidimensional array from string?

Posted: Fri Jul 09, 2021 7:32 pm
by dunbarx
@Richard

I sort of made that point in the line:

Code: Select all

 put line 3 of it into mayArray[line 1 of it][line 2 of it][x]
And I even used a non-existent variable to boot.

@Stam. Is what we both mentioned pertinent? If not, can you give a short snippet of code that you think will NOT do? And include a list of data that does not seem to work.

Craig

Re: Create multidimensional array from string?

Posted: Sat Jul 10, 2021 4:38 am
by rkriesel
stam wrote:
Fri Jul 09, 2021 5:44 pm
root | key1 | content1
root | key1 | content2
root | key1 | key2 | content3
root | key1 | key2 | content4
root | key3 | content5
Hi, stam. Here's one way to transform your text into your array:

Code: Select all

command compoundSplit @r
   repeat for each line l in r
      split l by "|"
      put "true" into it[l]
   end repeat
   put it into r
end compoundSplit
Here's a way to test that with your sample data:

Code: Select all

on mouseUp
   local t
   put "root|key1|content1" & cr after t
   put "root|key1|content2" & cr after t
   put "root|key1|key2|content3" & cr after t
   put "root|key1|key2|content4" & cr after t
   put "root|key3|content5" & cr after t
   breakpoint
   compoundSplit t
   breakpoint
end mouseUp
Does that work for you?

-- Dick

Re: Create multidimensional array from string?

Posted: Sat Jul 10, 2021 8:46 pm
by jacque
That's very clever. It works great but I'm not sure why. When a line is split, you get an array with three numeric keys:

1 root
2 key1
3 content1

Then somehow putting true into it[l] somehow creates an array with nested keys. How does that work?

Re: Create multidimensional array from string?

Posted: Sat Jul 10, 2021 10:29 pm
by stam
rkriesel wrote:
Sat Jul 10, 2021 4:38 am
Hi, stam. Here's one way to transform your text into your array:

Code: Select all

command compoundSplit @r
   repeat for each line l in r
      split l by "|"
      put "true" into it[l]
   end repeat
   put it into r
end compoundSplit
Hi Dick - this doesn't quite work. For one, it creates a key without a name with the value 'true'. For the other, it doesn't achieve the goal of putting the last value in the line as the content of the key. All keys have the content 'true'.

This is some actual data to process:

Code: Select all

0125870X|Tests|ECHO|LVEDV|211 ml
0125870X|Tests|ECHO|LVEF|42.6%
0125870X|Tests|Bloods|FBC|101
0125870X|Tests|Bloods|NTproBNP|712 ng/L
5552771M|Tests|ECHO|LVEDV|99 ml
5552771M|Tests|ECHO|LVEF|59%
5552771M|Diagnoses|Recovered LV dysfunction
basically the last item is the data to be stored in the key before it.

Using your algorithm, it almost works but i get this array back:
result.jpg
apart from the stray key the top, the problem here is that the "results" are stored as a keys, instead of the values of the keys. All keys hold the value 'true' instead...

Can't quite see the way to correct this, other than iterating through the text and putting the last item of each line into the array that was created and then deleting the last key of each array. Seems less elegant!

Re: Create multidimensional array from string?

Posted: Sat Jul 10, 2021 11:16 pm
by stam
rkriesel wrote:
Sat Jul 10, 2021 4:38 am
Does that work for you?
-- Dick
Hi Dick,
further to my previous post, i did manage to finally get it work as desired.
Still seems a bit like dark magic - your solution kind of worked but with some tweaking it did perfectly!
I should also say i had attempted something similar, but it failed spectacularly. My idea was to isolate the keys from the value, split the keys by the itemdelimiter and assign the value... but it didn't create a multidimensional array, just a array with keys with the name of the list of keys names containing the value at the end.

However using your suggestion i was able to finally get this to work:

Code: Select all

function compoundSplit pText
    local tArray, tValue
    set the itemDelimiter to "|"
    repeat for each line tLine in pText
        put item 1 to -2 of tLine into tArray // series of keys
        put item -1 of tLine into tValue // value
        split tArray by "|"
        put tValue into it[tArray]
    end repeat
    return it
end compoundSplit
produces the desired result:
result.jpg
Thanks for your invaluable help Dick!

====================================
EDIT: Just FYI, this fails if 2 keys have the same name - if multiple values are assigned to he same key in separate lines, these need to be numerically keyed.

Re: Create multidimensional array from string?

Posted: Sun Jul 11, 2021 12:07 am
by rkriesel
jacque wrote:
Sat Jul 10, 2021 8:46 pm
That's very clever. It works great but I'm not sure why. When a line is split, you get an array with three numeric keys:

1 root
2 key1
3 content1

Then somehow putting true into it[l] somehow creates an array with nested keys. How does that work?
The following excerpts provide a quote from Mark Waddingham:

On Mar 12, 2012, at 10:19 AM, Pete wrote:
I'm wondering how you found about about this key values array feature? I
can't find any mention of it in the dictionary or the reference manual and
it sure seems like something that should be known!
On Mar 12, 2012, at 1:18 PM, Dick Kriesel <dick.kriesel@mail.com> wrote:

I found it while looking through bug reports for arrays, in <http://quality.runrev.com/show_bug.cgi?id=7166> dated 2008-11-28. So, thanks be to Mark Waddingham and David Bovill for that.

For convenience, here's Mark's reply to David:
Thanks for the suggestion.

This is on the list to include for the next version. In that version with:
put tValue into tArray[tKey]
(indeed anywhere you can currently do tArray[tKey])

The meaning of 'tKey' will be extended:
1) If it is a string then it is as it is now
2) If it is a numerically keyed array starting at 1, then it will mean:
put tValue into tArray[tKey[1]][tKey[2]]...[tKey[n]]
where <n> is the number of elements in tKey
3) Otherwise it is an error.

This will allow you to construct an array containing the path to the key you
want to modify/fetch/delete dynamically.
I agree, the feature's worth adding into the dictionary and manual.

-- Dick
Does that answer your question, Jacque?

-- Dick

Re: Create multidimensional array from string?

Posted: Sun Jul 11, 2021 1:12 am
by rkriesel
stam wrote:
Sat Jul 10, 2021 10:29 pm
this doesn't quite work. For one, it creates a key without a name with the value 'true'. For the other, it doesn't achieve the goal of putting the last value in the line as the content of the key. All keys have the content 'true'.
@stam: I wrote it first as you originally specified:
The use-case i have in mind is for processing a return-delimited list where each line describes different keys & sub-keys of the same array, so would need to automate processing of each line and assign the final item of each line to the last sub-key of that particular branch...
But when it was ready, I saw that in your sample data, you showed some key combinations that had more than one "content."
stam wrote:
Fri Jul 09, 2021 5:44 pm
root | key1 | content1
root | key1 | content2
root | key1 | key2 | content3
root | key1 | key2 | content4
root | key3 | content5
So I mistakenly rewrote it before posting.

I'm glad it helped anyway.

-- Dick

Re: Create multidimensional array from string?

Posted: Sun Jul 11, 2021 2:53 am
by jacque
rkriesel wrote:
Sun Jul 11, 2021 12:07 am
Does that answer your question, Jacque?
Yes, it does. It even looks a bit familiar but I'd forgotten about it entirely. Thanks for the reminder, and for the trouble of looking up the reference.

Re: Create multidimensional array from string?

Posted: Sun Jul 11, 2021 5:24 am
by rkriesel
jacque wrote:
Sun Jul 11, 2021 2:53 am
rkriesel wrote:
Sun Jul 11, 2021 12:07 am
Does that answer your question, Jacque?
Yes, it does. It even looks a bit familiar but I'd forgotten about it entirely. Thanks for the reminder, and for the trouble of looking up the reference.
I posted replies containing that in '12, '13, '18, and now '21, so familiar is good. The content has lasting value.

You're very welcome, Jacque. You might even see it again someday.

-- Dick

Re: Create multidimensional array from string?

Posted: Sun Jul 11, 2021 11:53 am
by stam
rkriesel wrote:
Sun Jul 11, 2021 5:24 am
I posted replies containing that in '12, '13, '18, and now '21, so familiar is good. The content has lasting value.
You're very welcome, Jacque. You might even see it again someday.
-- Dick
to us newcomers your experience is invaluable - can't thank you enough for sharing and for making this forum the amazing place it is...