Thanks for another great solution, Sander. It does exactly what I needed.
Though I can't yet come up with solutions like these on my own, I have progressed to the point, after 9 months or so working with the Wolfram Language, where these types of solutions no longer seem like magic to me. To help those who still are baffled by solutions that nest several functions (and to help myself better understand this particular solution), I will pull Sander's code apart and explain:
The first step is to identify all the places in the data where a string goes to a list.
Cases[t, (x_String -> y_List), \[Infinity]]
Infinity is the level specification so that Cases will find the String->List pattern no matter how deeply nested it is.
:> f[x, y]
The code above then changes each String->List result by applying f[] to it.
f[x_, y_List] :=
The function f[] is defined for two parameters, x which is any expression and y which has to be a list. Since we are sending String/List pairs into the function, this should work every time.
Module[{y2},
This means that y2 will stay a local variable inside the module, which, I think, prevents the function from using old values of y2.
y2 = If[Head[#] === Rule, First[#], #] & /@ y;
Remember that y is a list. This code says that for every list element in y, the element in the list y2 is either y or the left-hand-side of y if y is a rule.
Thread[{y2, x}]
Thread[{{a, b, c}, d}] has the output of {{a, d}, {b, d}, {c, d}}, so this function makes a pair {y,x} of each element in y2.
StringRiffle[#, " \[Rule] "]
And for each of those pairs {y,x}, change them into a string "y ? x";
So far we have a bunch of lists, so the code below turns them into one long list.
result = Join @@
And finally Sander added // Column for pretty output.
I am still not 100% clear on how the delayed rule works in the line
Cases[t, (x_String -> y_List) :> f[x, y]
If I have made any mistakes in the above explanation, someone please correct me, for my sake and the sake of any who might try to learn from what I have written.
Some day I hope to be able to visualize solutions in Wolfram Language functions. Until then, I'm having fun experimenting and learning.
Thanks again, Sander.
Mark Greenberg