Message Boards Message Boards

0
|
2833 Views
|
8 Replies
|
2 Total Likes
View groups...
Share
Share this post:

Match a vector with specified length

Posted 1 year ago

I want to define a function parameter which has to be a 3D- or any-dimensional vector.

POSTED BY: Werner Geiger
8 Replies

Hello Werner

Hope you like this one:

In[25]:= MatchQ[{1, 20, 300}, {Repeated[Except[_List], 3]}]    
Out[25]= True

In[24]:= MatchQ[{1, {20}, 300}, {Repeated[Except[_List], 3]}]    
Out[24]= False

This follows exactly the Mathematica documentation of VectorQ

VectorQ[expr] gives True if expr is a list or a one-dimensional SparseArray object, none of whose elements are themselves lists, and gives False otherwise.

Last but not least:

MatchQ[{1, 20, 300}, _?(v \[Function] VectorQ@v && Length@v == 3)]
POSTED BY: Robert Nowak

Hi Werner

"would be not very readable" - why that?

MatchQ[{1, 20, 300}, {Repeated[_?NumericQ, 3]}]
POSTED BY: Robert Nowak
Posted 1 year ago

Robert, this solution with NumericQ works indeed. I had in mind that NumericQ was Listable, but it isn't.

MatchQ[{1, {20, 21}, 300}, {Repeated[_?NumericQ, 3]}]
(* False *)

But your original proposal does not really work since AtomQ accepts less expressions than VectorQ:

(* This works *)
b =.; vec = {1, b, 300};
{MatchQ[vec, {Repeated[_?AtomQ, 3]}], 
 MatchQ[vec, v : _ /; (VectorQ[v] && Length[v] == 3)]}
(* {True, True} *)

(* This doesn't work  *)
b = Sqrt[2]; vec = {1, b, 300};
{MatchQ[vec, {Repeated[_?AtomQ, 3]}], 
 MatchQ[vec, v : _ /; (VectorQ[v] && Length[v] == 3)]}
(* {False, True} *)

(* But at least for NumericQ, it works  *)
b = Sqrt[2]; vec = {1, b, 300};
{MatchQ[vec, {Repeated[_?NumericQ, 3]}], 
 MatchQ[vec, v : _ /; (VectorQ[v, NumericQ] && Length[v] == 3)]}
(* {True, True} *)
POSTED BY: Werner Geiger
MatchQ[{1, 20, 300}, {Repeated[_?AtomQ, 3]}]
POSTED BY: Robert Nowak
Posted 1 year ago

Yes Robert, this tests like VectorQ. But extending it to NumericQ would probably not be very readable.

POSTED BY: Werner Geiger
Posted 1 year ago

Why not just replace AtomQ with NumericQ?

POSTED BY: Eric Rimbey
Posted 1 year ago

I don't know what you're looking for in terms of "simpler", but I think it makes the subsequent code simpler if you wrap the conditions up in a well-named function. Parameterizing it also makes it "simpler" to extend later. Here's one way you could do that.

VectorTest[length_, test_][expr_] := 
 And[length == Length@expr, VectorQ[expr, test]]

Then your argument could be specified like this:

v_?(VectorTest[3, NumericQ])

(VectorTest is a pretty generic name, but you can probably come up with something better in your context.)

POSTED BY: Eric Rimbey
Posted 1 year ago

Thats a very good idea, Eric. Thank you. With some minor changes now I use:

ClearAll[myVectorLQ];
myVectorLQ[length_][expr_] := TrueQ[length == Length@expr] && VectorQ[expr]; 
myVectorLQ[length_, test_][expr_] := 
 TrueQ[length == Length@expr] && VectorQ[expr, test];

Then I can write:

ClearAll[fL, fLN];
fL[v_?(myVectorLQ[5])] := Style["fL OK", Blue, Bold];
fLN[v_?(myVectorLQ[5, NumericQ])] := Style["fLN OK", Blue, Bold];

a = Sqrt[2]; b =.;
Do[
  Print["v = ", Style[v, Bold], ", {fL[v],fLN[v]} = ", {fL[v], fLN[v]}];
  , {v, {{1, a, 3, 4, 5}, {1, a, b, 4, 5}, {1, {2 a}, 3, 4, 5}, {1, a, 3, 
     4}}}];

enter image description here

This also solves the problem of passing a default value:

ClearAll[fLD, fLND];
fLD[v : (_?(myVectorLQ[5])) : {1, 2, 3, 4, 5}] := Style["fLD OK", Blue, Bold];
fLND[v : (_?(myVectorLQ[5, NumericQ])) : {1, 2, 3, 4, 5}] := 
  Style["fLND OK", Blue, Bold];

a = Sqrt[2]; b =.;
Do[
  Print["v = ", Style[If[v != {}, First[v], v], Bold], 
    ", {fLD[v],fLND[v]} = ", {fLD @@ v, fLND @@ v}];
  , {v, {{{1, a, 3, 4, 5}}, {{1, a, b, 4, 5}}, {{1, {2 a}, 3, 4, 5}}, {{1, a, 
      3, 4}}, {}}}];

enter image description here

POSTED BY: Werner Geiger
Reply to this discussion
Community posts can be styled and formatted using the Markdown syntax.
Reply Preview
Attachments
Remove
or Discard

Group Abstract Group Abstract