List manipulation: conditional result based on variable-length sublists, part deux

This is an outgrowth of this question.

Suppose I have the following definitions:

eqexp = {a, b, c, d};
eqval = {e, f, g, h};
signval = {{}, {1}, {-1}, {1, -1}};
criteria = {{}, {i}, {j}, {k, l}};


As before, I want signval to determine whether the eqexp component is greater than or less than the eqval component. But now I have an extra list (criteria) which has the same structure as signval. I want the corresponding criteria value to be equal to zero as well, and then the resulting inequalities combined with an Or. So the desired output would be:

{False, b > f && i == 0, c < g && j == 0,
(d > h && k == 0) || (d < h && l == 0)}


The previous answers (without the criteria component) cleverly used a replacement rule on signval. I don't see how to do the same thing here. Any suggestions?

Or @@@ MapThread[
And @@@ Transpose[{#3 /. {1 -> #1 > #2, -1 -> #1 < #2}, Thread[#4 == 0]}] &,
{eqexp, eqval, signval, criteria}]


On further thought, another Thread feels better than the Transpose:

Or @@@ MapThread[
Thread[(#3 /. {1 -> #1 > #2, -1 -> #1 < #2}) && Thread[#4 == 0]] &,
{eqexp, eqval, signval, criteria}]

f0 = Function[, Construct @ ##, Listable];
Or @@@ f0[And,
f0[signval /. {1 -> Greater, -1 -> Less}, eqexp, eqval],
f0[EqualTo[0], criteria]]


{False, b > f && i == 0, c < g && j == 0, (d > h && k == 0) || (d < h && l == 0)}

• Why does your method not work if I define f0 = Construct@## &; SetAttributes[f0, Listable];? (Maybe this should be a full question by itself) – Roman Jul 6 at 12:47
• @Roman, great question; really puzzling. – kglr Jul 6 at 13:02
• I conclude that there are two ways of using attributes: (i) anonymous functions need the attributes assigned as the third argument of Function (not assigned to the variable holding the anonymous function, f0 in your case), and (ii) regular functions (with patterns on the LHS) need the attributes assigned with SetAttribute to the function head. Mixing these two different ways of using attributes gives poor results. – Roman Jul 6 at 13:57
• Roman, that brings out an important difference between specifying a pure function foo as foo = something& versus foo = Function[, something]. The latter seems to be the only way to assign Attributes to foo. – kglr Jul 6 at 14:45

And once again, I post a question and right away figure out an answer. Here it is (although I would absolutely welcome more efficient ways to do it):

Or @@ MapThread[And, #] & /@ MapThread[{#3 /. {1 -> #1 > #2, -1 -> #1 < #2},
Map[# == 0 &, #4]} &, {eqexp, eqval, signval, criteria}]