Checking if an integer is a member of an integer listMembership checking inside fpevalLaTeX for loop @forPackage to test whether a string is in a listIssue with Expansions of Nested MacrosFast membership test for integer lists/setsCan I defend against “Dimension too large” errors?Definition-time expansiton of command line inputConversion of a String to Integerhow to select a character (or word) from a listChecking if a variable is not nullDefine an expandable function for comparing a token list to a string in LaTeX3Replacing an id (integer) with a string?Integer and floating point accuracy in LaTeX3Unsigned integer variable in a regexpgfkey as integer for ifnumStringify input - string on token listMembership checking inside fpevalConversion of a String to Integer
Why should I "believe in" weak solutions to PDEs?
Does the length of a password for Wi-Fi affect speed?
Getting an entry level IT position later in life
Why is Chromosome 1 called Chromosome 1?
Does a 4 bladed prop have almost twice the thrust of a 2 bladed prop?
How do I get the =LEFT function in excel, to also take the number zero as the first number?
Does this put me at risk for identity theft?
Is a switch from R to Python worth it?
Generate a random point outside a given rectangle within a map
How to continue a line in Latex in math mode?
Print only the last three columns from file
Is this cheap "air conditioner" able to cool a room?
Secure my password from unsafe servers
What is an air conditioner compressor hard start kit and how does it work?
I was contacted by a private bank overseas to get my inheritance
Is DC heating faster than AC heating?
Using command line how to open a specific section of GUI System Preferences?
Best way to explain to my boss that I cannot attend a team summit because it is on Rosh Hashana or any other Jewish Holiday
How would a family travel from Indiana to Texas in 1911?
What can make Linux so unresponsive?
Can I enter a rental property without giving notice if I'm afraid a tenant may be hurt?
Pronouns when writing from the point of view of a robot
Can ads on a page read my password?
Can you use the Help action to give a 2019 UA Artillerist artificer's turret advantage?
Checking if an integer is a member of an integer list
Membership checking inside fpevalLaTeX for loop @forPackage to test whether a string is in a listIssue with Expansions of Nested MacrosFast membership test for integer lists/setsCan I defend against “Dimension too large” errors?Definition-time expansiton of command line inputConversion of a String to Integerhow to select a character (or word) from a listChecking if a variable is not nullDefine an expandable function for comparing a token list to a string in LaTeX3Replacing an id (integer) with a string?Integer and floating point accuracy in LaTeX3Unsigned integer variable in a regexpgfkey as integer for ifnumStringify input - string on token listMembership checking inside fpevalConversion of a String to Integer
.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty margin-bottom:0;
Is there any way to check whether an integer is a member of a list of integer numbers and return a boolean?
I found this neat solution, here that does a great job. It checks whether a string exists in a list of strings:
documentclassarticle
usepackagexstring
newcommandIfStringInList[2]IfSubStr,#2,,#1,
begindocument
IfStringInListPaulGeorge,John,Paul,RingoTrueFalse
enddocument
However, it does return a string not a boolean "true" or "false" and caused me some difficulty which is posted here.
Let's call the macro I would like to have ISMEMBER
. My goal is to use ISMEMBER
and examine whether an integer is in the list and depending on whether it is or not, perform some tasks, as an example:
fpeval ISMEMBER11,2,3,4,5 ? MACRO_FOR_MEMBERS : MACRO_FOR_NON_MEMBERS
Is such functionality possible?
macros strings comparison number l3fp
add a comment |
Is there any way to check whether an integer is a member of a list of integer numbers and return a boolean?
I found this neat solution, here that does a great job. It checks whether a string exists in a list of strings:
documentclassarticle
usepackagexstring
newcommandIfStringInList[2]IfSubStr,#2,,#1,
begindocument
IfStringInListPaulGeorge,John,Paul,RingoTrueFalse
enddocument
However, it does return a string not a boolean "true" or "false" and caused me some difficulty which is posted here.
Let's call the macro I would like to have ISMEMBER
. My goal is to use ISMEMBER
and examine whether an integer is in the list and depending on whether it is or not, perform some tasks, as an example:
fpeval ISMEMBER11,2,3,4,5 ? MACRO_FOR_MEMBERS : MACRO_FOR_NON_MEMBERS
Is such functionality possible?
macros strings comparison number l3fp
1
I think an answer to one of my questions might be helpful here: tex.stackexchange.com/a/496671/85504
– MarcinKonowalczyk
Jul 27 at 23:11
add a comment |
Is there any way to check whether an integer is a member of a list of integer numbers and return a boolean?
I found this neat solution, here that does a great job. It checks whether a string exists in a list of strings:
documentclassarticle
usepackagexstring
newcommandIfStringInList[2]IfSubStr,#2,,#1,
begindocument
IfStringInListPaulGeorge,John,Paul,RingoTrueFalse
enddocument
However, it does return a string not a boolean "true" or "false" and caused me some difficulty which is posted here.
Let's call the macro I would like to have ISMEMBER
. My goal is to use ISMEMBER
and examine whether an integer is in the list and depending on whether it is or not, perform some tasks, as an example:
fpeval ISMEMBER11,2,3,4,5 ? MACRO_FOR_MEMBERS : MACRO_FOR_NON_MEMBERS
Is such functionality possible?
macros strings comparison number l3fp
Is there any way to check whether an integer is a member of a list of integer numbers and return a boolean?
I found this neat solution, here that does a great job. It checks whether a string exists in a list of strings:
documentclassarticle
usepackagexstring
newcommandIfStringInList[2]IfSubStr,#2,,#1,
begindocument
IfStringInListPaulGeorge,John,Paul,RingoTrueFalse
enddocument
However, it does return a string not a boolean "true" or "false" and caused me some difficulty which is posted here.
Let's call the macro I would like to have ISMEMBER
. My goal is to use ISMEMBER
and examine whether an integer is in the list and depending on whether it is or not, perform some tasks, as an example:
fpeval ISMEMBER11,2,3,4,5 ? MACRO_FOR_MEMBERS : MACRO_FOR_NON_MEMBERS
Is such functionality possible?
macros strings comparison number l3fp
macros strings comparison number l3fp
edited Jul 28 at 0:16
Phelype Oleinik
32.4k7 gold badges56 silver badges111 bronze badges
32.4k7 gold badges56 silver badges111 bronze badges
asked Jul 27 at 22:35
AFPAFP
2,4475 gold badges28 silver badges57 bronze badges
2,4475 gold badges28 silver badges57 bronze badges
1
I think an answer to one of my questions might be helpful here: tex.stackexchange.com/a/496671/85504
– MarcinKonowalczyk
Jul 27 at 23:11
add a comment |
1
I think an answer to one of my questions might be helpful here: tex.stackexchange.com/a/496671/85504
– MarcinKonowalczyk
Jul 27 at 23:11
1
1
I think an answer to one of my questions might be helpful here: tex.stackexchange.com/a/496671/85504
– MarcinKonowalczyk
Jul 27 at 23:11
I think an answer to one of my questions might be helpful here: tex.stackexchange.com/a/496671/85504
– MarcinKonowalczyk
Jul 27 at 23:11
add a comment |
2 Answers
2
active
oldest
votes
You can use do a comma-separated list parser to loop through the list of items and check if the given item is present in the list. Since the comma-separated list can be read by using a delimited macro, this can be done expandably, allowing you to plug the macro into fpeval
to get the syntax you want.
Using expl3
(you are loading it with xfp
anyway) something like this would solve the problem:
ExplSyntaxOn
prg_new_conditional:Npnn afp_int_ismember:nn #1#2 p, T, F, TF
__afp_ismember_loop:nw #1 #2 , q_recursion_tail , q_recursion_stop
cs_new:Npn __afp_ismember_loop:nw #1#2,
quark_if_recursion_tail_stop_do:nn #2
prg_return_false:
int_compare:nNnTF #1 = #2
use_i_delimit_by_q_recursion_stop:nw prg_return_true:
__afp_ismember_loop:nw #1
ExplSyntaxOff
The code above defines a conditional afp_int_ismember:nn(TF)
, whose first argument is the item to check, and the second is the comma-separated list. The macro starts by expanding __afp_ismember_loop:nw
: this macro takes the item to be tested (#1
) and the first item in the list, delimited by a ,
(#2
). The macro tests the equality of #1
and #2
using int_compare:nNnTF
and issues prg_return_true:
if they are equal or calls __afp_ismember_loop:nw
for the next item. If the end of the list is found (i.e., q_recursion_tail
is grabbed), then the function issues prg_return_false:
because no match was found for #1
.
The code above can be tweaked to replace int_compare:nNnTF
by a generic equality comparison function. If you do that you can define wrappers around __afp_ismember_loop:nw
to create ismember
functions for different data types. The code below does that and defines two functions: afp_int_ismember:nn(TF)
(using int_compare:nNnTF
) and afp_str_ismember:nn(TF)
(using str_if_eq:eeTF
). Doing that you can even test if I'm a member of the Beatles!
To use the function in fpeval
you just need the predicate form (afp_int_ismember_p:nn
) of the conditional function:
fpeval afp_int_ismember_p:nn 1 1,2,3,4,5 ? 123 : 321
And the string version would also work here:
fpeval afp_str_ismember_p:nn Phelype George,John,Paul,Ringo ? 123 : 321
Full code:
documentclassarticle
usepackageexpl3
usepackagexparse
usepackagexfp
ExplSyntaxOn
% Core code for the membership test
cs_new:Npn __afp_ismember_loop:Nnw #1#2#3,
quark_if_recursion_tail_stop_do:nn #3
prg_return_false:
#1 #2 #3
use_i_delimit_by_q_recursion_stop:nw prg_return_true:
__afp_ismember_loop:Nnw #1 #2
% Wrapper for testing integers
prg_new_conditional:Npnn afp_int_ismember:nn #1#2 p, T, F, TF
__afp_ismember_loop:Nnw __afp_int_isequal:nnTF #1 #2 ,
q_recursion_tail , q_recursion_stop
prg_new_conditional:Npnn __afp_int_isequal:nn #1#2 p, T, F, TF
int_compare:nNnTF #1 = #2
prg_return_true:
prg_return_false:
% Wrappers for testing strings
% With expansion
prg_new_conditional:Npnn afp_str_ismember:ee #1#2 p, T, F, TF
__afp_ismember_loop:Nnw str_if_eq:eeTF #1 #2 ,
q_recursion_tail , q_recursion_stop
% Without expansion
prg_new_conditional:Npnn afp_str_ismember:nn #1#2 p, T, F, TF
__afp_ismember_loop:Nnw str_if_eq:nnTF #1 #2 ,
q_recursion_tail , q_recursion_stop
% Sample commands
NewExpandableDocumentCommand IntIsmember m m
afp_int_ismember:nnTF #1 #2
#1~is~member~of~`#2'
#1~is~emphnot~member~of~`#2'
NewExpandableDocumentCommand StrIsmember m m
afp_str_ismember:nnTF #1 #2
#1~is~member~of~`#2'
#1~is~emphnot~member~of~`#2'
ExplSyntaxOff
begindocument
IntIsmember11,2,3
IntIsmember41,2,3
StrIsmemberPaulGeorge,John,Paul,Ringo
textbfStrIsmemberPhelypeGeorge,John,Paul,Ringo
ExplSyntaxOn
fpeval afp_int_ismember_p:nn 1 1,2,3,4,5 ? 123 : 321 par
fpeval afp_str_ismember_p:nn Phelype George,John,Paul,Ringo ? 123 : 321
ExplSyntaxOff
enddocument
That answer makes me wonder why there isn't an expandableclist_if_in:nn(TF)
– siracusa
Jul 28 at 2:28
1
@siracusa There could be... Please, do ask :-) The only problem I see is that we would possibly need aclist_str_if_in:nn(TF)
and aclist_tl_if_in:nn(TF)
(and potentially others) because the onlyclist
y thing here is that the function looks up something in aclist
: the actual data type in theclist var
would need to be queried... Perhapsstr_if_in_clist:nn
andtl_if_in_clist:nn
andint_if_in_clist:nn
...
– Phelype Oleinik
Jul 28 at 2:33
@PhelypeOleinik Very nice! Any reason you usecs_new:Npn
instead ofNewExpandableDocumentCommand
for the document-level commands? Is it that you don't want to loadxparse
, maybe? Or... are you a rebel? :)
– frougon
Jul 28 at 6:28
@frougon A rebel, probably ;-) Actually I didn't even think of it: theIntIsmember
andStrIsmember
commands are just examples. But you're right,xparse
is better here. Thanks :-)
– Phelype Oleinik
Jul 28 at 16:09
add a comment |
Something like this? The macro name is inspired by the Mathematica command MemberQ
, and the code comes from here. This solution does not require any packages.
documentclassarticle
newififmember
makeatletter% for @for see e.g. https://tex.stackexchange.com/a/100684/121799
%from https://tex.stackexchange.com/a/498576/121799
newcommandMemberQ[2]globalmemberfalse%
@fornext:=#1doifnumnext=#2globalmembertruefi
makeatother
begindocument
MemberQ1,2,3,42
ifmember 2 is in list fi
MemberQ1,2,3,45
ifmember 5 is in listelse%
5 is not in the listfi
enddocument
4
Oh, an answer of @marmot that does not include anything from TikZ!?! I MUST READ IT.
– manooooh
Jul 28 at 0:05
1
@manooooh This is a great solution and also compact. I wish I could select two accepted answers. Can this be used inside afpeval
? Thanks for your time.
– AFP
Jul 28 at 0:40
3
@AFP No, it cannot because it isn't expandable (@for
isn't expandable because it does assignments, andmembertrue
andmemberfalse
are also assignments, so not expandable). The expandability ofl3fp
allows you to use it virtually anywhere TeX expects a number (see this trick, for example). The downside of this expandability is that everything inside an expression must be expandable too.
– Phelype Oleinik
Jul 28 at 2:19
add a comment |
Your Answer
StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "85"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);
else
createEditor();
);
function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: false,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
imageUploader:
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
,
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);
);
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2ftex.stackexchange.com%2fquestions%2f501773%2fchecking-if-an-integer-is-a-member-of-an-integer-list%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
You can use do a comma-separated list parser to loop through the list of items and check if the given item is present in the list. Since the comma-separated list can be read by using a delimited macro, this can be done expandably, allowing you to plug the macro into fpeval
to get the syntax you want.
Using expl3
(you are loading it with xfp
anyway) something like this would solve the problem:
ExplSyntaxOn
prg_new_conditional:Npnn afp_int_ismember:nn #1#2 p, T, F, TF
__afp_ismember_loop:nw #1 #2 , q_recursion_tail , q_recursion_stop
cs_new:Npn __afp_ismember_loop:nw #1#2,
quark_if_recursion_tail_stop_do:nn #2
prg_return_false:
int_compare:nNnTF #1 = #2
use_i_delimit_by_q_recursion_stop:nw prg_return_true:
__afp_ismember_loop:nw #1
ExplSyntaxOff
The code above defines a conditional afp_int_ismember:nn(TF)
, whose first argument is the item to check, and the second is the comma-separated list. The macro starts by expanding __afp_ismember_loop:nw
: this macro takes the item to be tested (#1
) and the first item in the list, delimited by a ,
(#2
). The macro tests the equality of #1
and #2
using int_compare:nNnTF
and issues prg_return_true:
if they are equal or calls __afp_ismember_loop:nw
for the next item. If the end of the list is found (i.e., q_recursion_tail
is grabbed), then the function issues prg_return_false:
because no match was found for #1
.
The code above can be tweaked to replace int_compare:nNnTF
by a generic equality comparison function. If you do that you can define wrappers around __afp_ismember_loop:nw
to create ismember
functions for different data types. The code below does that and defines two functions: afp_int_ismember:nn(TF)
(using int_compare:nNnTF
) and afp_str_ismember:nn(TF)
(using str_if_eq:eeTF
). Doing that you can even test if I'm a member of the Beatles!
To use the function in fpeval
you just need the predicate form (afp_int_ismember_p:nn
) of the conditional function:
fpeval afp_int_ismember_p:nn 1 1,2,3,4,5 ? 123 : 321
And the string version would also work here:
fpeval afp_str_ismember_p:nn Phelype George,John,Paul,Ringo ? 123 : 321
Full code:
documentclassarticle
usepackageexpl3
usepackagexparse
usepackagexfp
ExplSyntaxOn
% Core code for the membership test
cs_new:Npn __afp_ismember_loop:Nnw #1#2#3,
quark_if_recursion_tail_stop_do:nn #3
prg_return_false:
#1 #2 #3
use_i_delimit_by_q_recursion_stop:nw prg_return_true:
__afp_ismember_loop:Nnw #1 #2
% Wrapper for testing integers
prg_new_conditional:Npnn afp_int_ismember:nn #1#2 p, T, F, TF
__afp_ismember_loop:Nnw __afp_int_isequal:nnTF #1 #2 ,
q_recursion_tail , q_recursion_stop
prg_new_conditional:Npnn __afp_int_isequal:nn #1#2 p, T, F, TF
int_compare:nNnTF #1 = #2
prg_return_true:
prg_return_false:
% Wrappers for testing strings
% With expansion
prg_new_conditional:Npnn afp_str_ismember:ee #1#2 p, T, F, TF
__afp_ismember_loop:Nnw str_if_eq:eeTF #1 #2 ,
q_recursion_tail , q_recursion_stop
% Without expansion
prg_new_conditional:Npnn afp_str_ismember:nn #1#2 p, T, F, TF
__afp_ismember_loop:Nnw str_if_eq:nnTF #1 #2 ,
q_recursion_tail , q_recursion_stop
% Sample commands
NewExpandableDocumentCommand IntIsmember m m
afp_int_ismember:nnTF #1 #2
#1~is~member~of~`#2'
#1~is~emphnot~member~of~`#2'
NewExpandableDocumentCommand StrIsmember m m
afp_str_ismember:nnTF #1 #2
#1~is~member~of~`#2'
#1~is~emphnot~member~of~`#2'
ExplSyntaxOff
begindocument
IntIsmember11,2,3
IntIsmember41,2,3
StrIsmemberPaulGeorge,John,Paul,Ringo
textbfStrIsmemberPhelypeGeorge,John,Paul,Ringo
ExplSyntaxOn
fpeval afp_int_ismember_p:nn 1 1,2,3,4,5 ? 123 : 321 par
fpeval afp_str_ismember_p:nn Phelype George,John,Paul,Ringo ? 123 : 321
ExplSyntaxOff
enddocument
That answer makes me wonder why there isn't an expandableclist_if_in:nn(TF)
– siracusa
Jul 28 at 2:28
1
@siracusa There could be... Please, do ask :-) The only problem I see is that we would possibly need aclist_str_if_in:nn(TF)
and aclist_tl_if_in:nn(TF)
(and potentially others) because the onlyclist
y thing here is that the function looks up something in aclist
: the actual data type in theclist var
would need to be queried... Perhapsstr_if_in_clist:nn
andtl_if_in_clist:nn
andint_if_in_clist:nn
...
– Phelype Oleinik
Jul 28 at 2:33
@PhelypeOleinik Very nice! Any reason you usecs_new:Npn
instead ofNewExpandableDocumentCommand
for the document-level commands? Is it that you don't want to loadxparse
, maybe? Or... are you a rebel? :)
– frougon
Jul 28 at 6:28
@frougon A rebel, probably ;-) Actually I didn't even think of it: theIntIsmember
andStrIsmember
commands are just examples. But you're right,xparse
is better here. Thanks :-)
– Phelype Oleinik
Jul 28 at 16:09
add a comment |
You can use do a comma-separated list parser to loop through the list of items and check if the given item is present in the list. Since the comma-separated list can be read by using a delimited macro, this can be done expandably, allowing you to plug the macro into fpeval
to get the syntax you want.
Using expl3
(you are loading it with xfp
anyway) something like this would solve the problem:
ExplSyntaxOn
prg_new_conditional:Npnn afp_int_ismember:nn #1#2 p, T, F, TF
__afp_ismember_loop:nw #1 #2 , q_recursion_tail , q_recursion_stop
cs_new:Npn __afp_ismember_loop:nw #1#2,
quark_if_recursion_tail_stop_do:nn #2
prg_return_false:
int_compare:nNnTF #1 = #2
use_i_delimit_by_q_recursion_stop:nw prg_return_true:
__afp_ismember_loop:nw #1
ExplSyntaxOff
The code above defines a conditional afp_int_ismember:nn(TF)
, whose first argument is the item to check, and the second is the comma-separated list. The macro starts by expanding __afp_ismember_loop:nw
: this macro takes the item to be tested (#1
) and the first item in the list, delimited by a ,
(#2
). The macro tests the equality of #1
and #2
using int_compare:nNnTF
and issues prg_return_true:
if they are equal or calls __afp_ismember_loop:nw
for the next item. If the end of the list is found (i.e., q_recursion_tail
is grabbed), then the function issues prg_return_false:
because no match was found for #1
.
The code above can be tweaked to replace int_compare:nNnTF
by a generic equality comparison function. If you do that you can define wrappers around __afp_ismember_loop:nw
to create ismember
functions for different data types. The code below does that and defines two functions: afp_int_ismember:nn(TF)
(using int_compare:nNnTF
) and afp_str_ismember:nn(TF)
(using str_if_eq:eeTF
). Doing that you can even test if I'm a member of the Beatles!
To use the function in fpeval
you just need the predicate form (afp_int_ismember_p:nn
) of the conditional function:
fpeval afp_int_ismember_p:nn 1 1,2,3,4,5 ? 123 : 321
And the string version would also work here:
fpeval afp_str_ismember_p:nn Phelype George,John,Paul,Ringo ? 123 : 321
Full code:
documentclassarticle
usepackageexpl3
usepackagexparse
usepackagexfp
ExplSyntaxOn
% Core code for the membership test
cs_new:Npn __afp_ismember_loop:Nnw #1#2#3,
quark_if_recursion_tail_stop_do:nn #3
prg_return_false:
#1 #2 #3
use_i_delimit_by_q_recursion_stop:nw prg_return_true:
__afp_ismember_loop:Nnw #1 #2
% Wrapper for testing integers
prg_new_conditional:Npnn afp_int_ismember:nn #1#2 p, T, F, TF
__afp_ismember_loop:Nnw __afp_int_isequal:nnTF #1 #2 ,
q_recursion_tail , q_recursion_stop
prg_new_conditional:Npnn __afp_int_isequal:nn #1#2 p, T, F, TF
int_compare:nNnTF #1 = #2
prg_return_true:
prg_return_false:
% Wrappers for testing strings
% With expansion
prg_new_conditional:Npnn afp_str_ismember:ee #1#2 p, T, F, TF
__afp_ismember_loop:Nnw str_if_eq:eeTF #1 #2 ,
q_recursion_tail , q_recursion_stop
% Without expansion
prg_new_conditional:Npnn afp_str_ismember:nn #1#2 p, T, F, TF
__afp_ismember_loop:Nnw str_if_eq:nnTF #1 #2 ,
q_recursion_tail , q_recursion_stop
% Sample commands
NewExpandableDocumentCommand IntIsmember m m
afp_int_ismember:nnTF #1 #2
#1~is~member~of~`#2'
#1~is~emphnot~member~of~`#2'
NewExpandableDocumentCommand StrIsmember m m
afp_str_ismember:nnTF #1 #2
#1~is~member~of~`#2'
#1~is~emphnot~member~of~`#2'
ExplSyntaxOff
begindocument
IntIsmember11,2,3
IntIsmember41,2,3
StrIsmemberPaulGeorge,John,Paul,Ringo
textbfStrIsmemberPhelypeGeorge,John,Paul,Ringo
ExplSyntaxOn
fpeval afp_int_ismember_p:nn 1 1,2,3,4,5 ? 123 : 321 par
fpeval afp_str_ismember_p:nn Phelype George,John,Paul,Ringo ? 123 : 321
ExplSyntaxOff
enddocument
That answer makes me wonder why there isn't an expandableclist_if_in:nn(TF)
– siracusa
Jul 28 at 2:28
1
@siracusa There could be... Please, do ask :-) The only problem I see is that we would possibly need aclist_str_if_in:nn(TF)
and aclist_tl_if_in:nn(TF)
(and potentially others) because the onlyclist
y thing here is that the function looks up something in aclist
: the actual data type in theclist var
would need to be queried... Perhapsstr_if_in_clist:nn
andtl_if_in_clist:nn
andint_if_in_clist:nn
...
– Phelype Oleinik
Jul 28 at 2:33
@PhelypeOleinik Very nice! Any reason you usecs_new:Npn
instead ofNewExpandableDocumentCommand
for the document-level commands? Is it that you don't want to loadxparse
, maybe? Or... are you a rebel? :)
– frougon
Jul 28 at 6:28
@frougon A rebel, probably ;-) Actually I didn't even think of it: theIntIsmember
andStrIsmember
commands are just examples. But you're right,xparse
is better here. Thanks :-)
– Phelype Oleinik
Jul 28 at 16:09
add a comment |
You can use do a comma-separated list parser to loop through the list of items and check if the given item is present in the list. Since the comma-separated list can be read by using a delimited macro, this can be done expandably, allowing you to plug the macro into fpeval
to get the syntax you want.
Using expl3
(you are loading it with xfp
anyway) something like this would solve the problem:
ExplSyntaxOn
prg_new_conditional:Npnn afp_int_ismember:nn #1#2 p, T, F, TF
__afp_ismember_loop:nw #1 #2 , q_recursion_tail , q_recursion_stop
cs_new:Npn __afp_ismember_loop:nw #1#2,
quark_if_recursion_tail_stop_do:nn #2
prg_return_false:
int_compare:nNnTF #1 = #2
use_i_delimit_by_q_recursion_stop:nw prg_return_true:
__afp_ismember_loop:nw #1
ExplSyntaxOff
The code above defines a conditional afp_int_ismember:nn(TF)
, whose first argument is the item to check, and the second is the comma-separated list. The macro starts by expanding __afp_ismember_loop:nw
: this macro takes the item to be tested (#1
) and the first item in the list, delimited by a ,
(#2
). The macro tests the equality of #1
and #2
using int_compare:nNnTF
and issues prg_return_true:
if they are equal or calls __afp_ismember_loop:nw
for the next item. If the end of the list is found (i.e., q_recursion_tail
is grabbed), then the function issues prg_return_false:
because no match was found for #1
.
The code above can be tweaked to replace int_compare:nNnTF
by a generic equality comparison function. If you do that you can define wrappers around __afp_ismember_loop:nw
to create ismember
functions for different data types. The code below does that and defines two functions: afp_int_ismember:nn(TF)
(using int_compare:nNnTF
) and afp_str_ismember:nn(TF)
(using str_if_eq:eeTF
). Doing that you can even test if I'm a member of the Beatles!
To use the function in fpeval
you just need the predicate form (afp_int_ismember_p:nn
) of the conditional function:
fpeval afp_int_ismember_p:nn 1 1,2,3,4,5 ? 123 : 321
And the string version would also work here:
fpeval afp_str_ismember_p:nn Phelype George,John,Paul,Ringo ? 123 : 321
Full code:
documentclassarticle
usepackageexpl3
usepackagexparse
usepackagexfp
ExplSyntaxOn
% Core code for the membership test
cs_new:Npn __afp_ismember_loop:Nnw #1#2#3,
quark_if_recursion_tail_stop_do:nn #3
prg_return_false:
#1 #2 #3
use_i_delimit_by_q_recursion_stop:nw prg_return_true:
__afp_ismember_loop:Nnw #1 #2
% Wrapper for testing integers
prg_new_conditional:Npnn afp_int_ismember:nn #1#2 p, T, F, TF
__afp_ismember_loop:Nnw __afp_int_isequal:nnTF #1 #2 ,
q_recursion_tail , q_recursion_stop
prg_new_conditional:Npnn __afp_int_isequal:nn #1#2 p, T, F, TF
int_compare:nNnTF #1 = #2
prg_return_true:
prg_return_false:
% Wrappers for testing strings
% With expansion
prg_new_conditional:Npnn afp_str_ismember:ee #1#2 p, T, F, TF
__afp_ismember_loop:Nnw str_if_eq:eeTF #1 #2 ,
q_recursion_tail , q_recursion_stop
% Without expansion
prg_new_conditional:Npnn afp_str_ismember:nn #1#2 p, T, F, TF
__afp_ismember_loop:Nnw str_if_eq:nnTF #1 #2 ,
q_recursion_tail , q_recursion_stop
% Sample commands
NewExpandableDocumentCommand IntIsmember m m
afp_int_ismember:nnTF #1 #2
#1~is~member~of~`#2'
#1~is~emphnot~member~of~`#2'
NewExpandableDocumentCommand StrIsmember m m
afp_str_ismember:nnTF #1 #2
#1~is~member~of~`#2'
#1~is~emphnot~member~of~`#2'
ExplSyntaxOff
begindocument
IntIsmember11,2,3
IntIsmember41,2,3
StrIsmemberPaulGeorge,John,Paul,Ringo
textbfStrIsmemberPhelypeGeorge,John,Paul,Ringo
ExplSyntaxOn
fpeval afp_int_ismember_p:nn 1 1,2,3,4,5 ? 123 : 321 par
fpeval afp_str_ismember_p:nn Phelype George,John,Paul,Ringo ? 123 : 321
ExplSyntaxOff
enddocument
You can use do a comma-separated list parser to loop through the list of items and check if the given item is present in the list. Since the comma-separated list can be read by using a delimited macro, this can be done expandably, allowing you to plug the macro into fpeval
to get the syntax you want.
Using expl3
(you are loading it with xfp
anyway) something like this would solve the problem:
ExplSyntaxOn
prg_new_conditional:Npnn afp_int_ismember:nn #1#2 p, T, F, TF
__afp_ismember_loop:nw #1 #2 , q_recursion_tail , q_recursion_stop
cs_new:Npn __afp_ismember_loop:nw #1#2,
quark_if_recursion_tail_stop_do:nn #2
prg_return_false:
int_compare:nNnTF #1 = #2
use_i_delimit_by_q_recursion_stop:nw prg_return_true:
__afp_ismember_loop:nw #1
ExplSyntaxOff
The code above defines a conditional afp_int_ismember:nn(TF)
, whose first argument is the item to check, and the second is the comma-separated list. The macro starts by expanding __afp_ismember_loop:nw
: this macro takes the item to be tested (#1
) and the first item in the list, delimited by a ,
(#2
). The macro tests the equality of #1
and #2
using int_compare:nNnTF
and issues prg_return_true:
if they are equal or calls __afp_ismember_loop:nw
for the next item. If the end of the list is found (i.e., q_recursion_tail
is grabbed), then the function issues prg_return_false:
because no match was found for #1
.
The code above can be tweaked to replace int_compare:nNnTF
by a generic equality comparison function. If you do that you can define wrappers around __afp_ismember_loop:nw
to create ismember
functions for different data types. The code below does that and defines two functions: afp_int_ismember:nn(TF)
(using int_compare:nNnTF
) and afp_str_ismember:nn(TF)
(using str_if_eq:eeTF
). Doing that you can even test if I'm a member of the Beatles!
To use the function in fpeval
you just need the predicate form (afp_int_ismember_p:nn
) of the conditional function:
fpeval afp_int_ismember_p:nn 1 1,2,3,4,5 ? 123 : 321
And the string version would also work here:
fpeval afp_str_ismember_p:nn Phelype George,John,Paul,Ringo ? 123 : 321
Full code:
documentclassarticle
usepackageexpl3
usepackagexparse
usepackagexfp
ExplSyntaxOn
% Core code for the membership test
cs_new:Npn __afp_ismember_loop:Nnw #1#2#3,
quark_if_recursion_tail_stop_do:nn #3
prg_return_false:
#1 #2 #3
use_i_delimit_by_q_recursion_stop:nw prg_return_true:
__afp_ismember_loop:Nnw #1 #2
% Wrapper for testing integers
prg_new_conditional:Npnn afp_int_ismember:nn #1#2 p, T, F, TF
__afp_ismember_loop:Nnw __afp_int_isequal:nnTF #1 #2 ,
q_recursion_tail , q_recursion_stop
prg_new_conditional:Npnn __afp_int_isequal:nn #1#2 p, T, F, TF
int_compare:nNnTF #1 = #2
prg_return_true:
prg_return_false:
% Wrappers for testing strings
% With expansion
prg_new_conditional:Npnn afp_str_ismember:ee #1#2 p, T, F, TF
__afp_ismember_loop:Nnw str_if_eq:eeTF #1 #2 ,
q_recursion_tail , q_recursion_stop
% Without expansion
prg_new_conditional:Npnn afp_str_ismember:nn #1#2 p, T, F, TF
__afp_ismember_loop:Nnw str_if_eq:nnTF #1 #2 ,
q_recursion_tail , q_recursion_stop
% Sample commands
NewExpandableDocumentCommand IntIsmember m m
afp_int_ismember:nnTF #1 #2
#1~is~member~of~`#2'
#1~is~emphnot~member~of~`#2'
NewExpandableDocumentCommand StrIsmember m m
afp_str_ismember:nnTF #1 #2
#1~is~member~of~`#2'
#1~is~emphnot~member~of~`#2'
ExplSyntaxOff
begindocument
IntIsmember11,2,3
IntIsmember41,2,3
StrIsmemberPaulGeorge,John,Paul,Ringo
textbfStrIsmemberPhelypeGeorge,John,Paul,Ringo
ExplSyntaxOn
fpeval afp_int_ismember_p:nn 1 1,2,3,4,5 ? 123 : 321 par
fpeval afp_str_ismember_p:nn Phelype George,John,Paul,Ringo ? 123 : 321
ExplSyntaxOff
enddocument
edited Jul 28 at 23:03
answered Jul 28 at 0:15
Phelype OleinikPhelype Oleinik
32.4k7 gold badges56 silver badges111 bronze badges
32.4k7 gold badges56 silver badges111 bronze badges
That answer makes me wonder why there isn't an expandableclist_if_in:nn(TF)
– siracusa
Jul 28 at 2:28
1
@siracusa There could be... Please, do ask :-) The only problem I see is that we would possibly need aclist_str_if_in:nn(TF)
and aclist_tl_if_in:nn(TF)
(and potentially others) because the onlyclist
y thing here is that the function looks up something in aclist
: the actual data type in theclist var
would need to be queried... Perhapsstr_if_in_clist:nn
andtl_if_in_clist:nn
andint_if_in_clist:nn
...
– Phelype Oleinik
Jul 28 at 2:33
@PhelypeOleinik Very nice! Any reason you usecs_new:Npn
instead ofNewExpandableDocumentCommand
for the document-level commands? Is it that you don't want to loadxparse
, maybe? Or... are you a rebel? :)
– frougon
Jul 28 at 6:28
@frougon A rebel, probably ;-) Actually I didn't even think of it: theIntIsmember
andStrIsmember
commands are just examples. But you're right,xparse
is better here. Thanks :-)
– Phelype Oleinik
Jul 28 at 16:09
add a comment |
That answer makes me wonder why there isn't an expandableclist_if_in:nn(TF)
– siracusa
Jul 28 at 2:28
1
@siracusa There could be... Please, do ask :-) The only problem I see is that we would possibly need aclist_str_if_in:nn(TF)
and aclist_tl_if_in:nn(TF)
(and potentially others) because the onlyclist
y thing here is that the function looks up something in aclist
: the actual data type in theclist var
would need to be queried... Perhapsstr_if_in_clist:nn
andtl_if_in_clist:nn
andint_if_in_clist:nn
...
– Phelype Oleinik
Jul 28 at 2:33
@PhelypeOleinik Very nice! Any reason you usecs_new:Npn
instead ofNewExpandableDocumentCommand
for the document-level commands? Is it that you don't want to loadxparse
, maybe? Or... are you a rebel? :)
– frougon
Jul 28 at 6:28
@frougon A rebel, probably ;-) Actually I didn't even think of it: theIntIsmember
andStrIsmember
commands are just examples. But you're right,xparse
is better here. Thanks :-)
– Phelype Oleinik
Jul 28 at 16:09
That answer makes me wonder why there isn't an expandable
clist_if_in:nn(TF)
– siracusa
Jul 28 at 2:28
That answer makes me wonder why there isn't an expandable
clist_if_in:nn(TF)
– siracusa
Jul 28 at 2:28
1
1
@siracusa There could be... Please, do ask :-) The only problem I see is that we would possibly need a
clist_str_if_in:nn(TF)
and a clist_tl_if_in:nn(TF)
(and potentially others) because the only clist
y thing here is that the function looks up something in a clist
: the actual data type in the clist var
would need to be queried... Perhaps str_if_in_clist:nn
and tl_if_in_clist:nn
and int_if_in_clist:nn
...– Phelype Oleinik
Jul 28 at 2:33
@siracusa There could be... Please, do ask :-) The only problem I see is that we would possibly need a
clist_str_if_in:nn(TF)
and a clist_tl_if_in:nn(TF)
(and potentially others) because the only clist
y thing here is that the function looks up something in a clist
: the actual data type in the clist var
would need to be queried... Perhaps str_if_in_clist:nn
and tl_if_in_clist:nn
and int_if_in_clist:nn
...– Phelype Oleinik
Jul 28 at 2:33
@PhelypeOleinik Very nice! Any reason you use
cs_new:Npn
instead of NewExpandableDocumentCommand
for the document-level commands? Is it that you don't want to load xparse
, maybe? Or... are you a rebel? :)– frougon
Jul 28 at 6:28
@PhelypeOleinik Very nice! Any reason you use
cs_new:Npn
instead of NewExpandableDocumentCommand
for the document-level commands? Is it that you don't want to load xparse
, maybe? Or... are you a rebel? :)– frougon
Jul 28 at 6:28
@frougon A rebel, probably ;-) Actually I didn't even think of it: the
IntIsmember
and StrIsmember
commands are just examples. But you're right, xparse
is better here. Thanks :-)– Phelype Oleinik
Jul 28 at 16:09
@frougon A rebel, probably ;-) Actually I didn't even think of it: the
IntIsmember
and StrIsmember
commands are just examples. But you're right, xparse
is better here. Thanks :-)– Phelype Oleinik
Jul 28 at 16:09
add a comment |
Something like this? The macro name is inspired by the Mathematica command MemberQ
, and the code comes from here. This solution does not require any packages.
documentclassarticle
newififmember
makeatletter% for @for see e.g. https://tex.stackexchange.com/a/100684/121799
%from https://tex.stackexchange.com/a/498576/121799
newcommandMemberQ[2]globalmemberfalse%
@fornext:=#1doifnumnext=#2globalmembertruefi
makeatother
begindocument
MemberQ1,2,3,42
ifmember 2 is in list fi
MemberQ1,2,3,45
ifmember 5 is in listelse%
5 is not in the listfi
enddocument
4
Oh, an answer of @marmot that does not include anything from TikZ!?! I MUST READ IT.
– manooooh
Jul 28 at 0:05
1
@manooooh This is a great solution and also compact. I wish I could select two accepted answers. Can this be used inside afpeval
? Thanks for your time.
– AFP
Jul 28 at 0:40
3
@AFP No, it cannot because it isn't expandable (@for
isn't expandable because it does assignments, andmembertrue
andmemberfalse
are also assignments, so not expandable). The expandability ofl3fp
allows you to use it virtually anywhere TeX expects a number (see this trick, for example). The downside of this expandability is that everything inside an expression must be expandable too.
– Phelype Oleinik
Jul 28 at 2:19
add a comment |
Something like this? The macro name is inspired by the Mathematica command MemberQ
, and the code comes from here. This solution does not require any packages.
documentclassarticle
newififmember
makeatletter% for @for see e.g. https://tex.stackexchange.com/a/100684/121799
%from https://tex.stackexchange.com/a/498576/121799
newcommandMemberQ[2]globalmemberfalse%
@fornext:=#1doifnumnext=#2globalmembertruefi
makeatother
begindocument
MemberQ1,2,3,42
ifmember 2 is in list fi
MemberQ1,2,3,45
ifmember 5 is in listelse%
5 is not in the listfi
enddocument
4
Oh, an answer of @marmot that does not include anything from TikZ!?! I MUST READ IT.
– manooooh
Jul 28 at 0:05
1
@manooooh This is a great solution and also compact. I wish I could select two accepted answers. Can this be used inside afpeval
? Thanks for your time.
– AFP
Jul 28 at 0:40
3
@AFP No, it cannot because it isn't expandable (@for
isn't expandable because it does assignments, andmembertrue
andmemberfalse
are also assignments, so not expandable). The expandability ofl3fp
allows you to use it virtually anywhere TeX expects a number (see this trick, for example). The downside of this expandability is that everything inside an expression must be expandable too.
– Phelype Oleinik
Jul 28 at 2:19
add a comment |
Something like this? The macro name is inspired by the Mathematica command MemberQ
, and the code comes from here. This solution does not require any packages.
documentclassarticle
newififmember
makeatletter% for @for see e.g. https://tex.stackexchange.com/a/100684/121799
%from https://tex.stackexchange.com/a/498576/121799
newcommandMemberQ[2]globalmemberfalse%
@fornext:=#1doifnumnext=#2globalmembertruefi
makeatother
begindocument
MemberQ1,2,3,42
ifmember 2 is in list fi
MemberQ1,2,3,45
ifmember 5 is in listelse%
5 is not in the listfi
enddocument
Something like this? The macro name is inspired by the Mathematica command MemberQ
, and the code comes from here. This solution does not require any packages.
documentclassarticle
newififmember
makeatletter% for @for see e.g. https://tex.stackexchange.com/a/100684/121799
%from https://tex.stackexchange.com/a/498576/121799
newcommandMemberQ[2]globalmemberfalse%
@fornext:=#1doifnumnext=#2globalmembertruefi
makeatother
begindocument
MemberQ1,2,3,42
ifmember 2 is in list fi
MemberQ1,2,3,45
ifmember 5 is in listelse%
5 is not in the listfi
enddocument
edited Jul 28 at 0:01
answered Jul 27 at 23:56
user121799user121799
126k6 gold badges192 silver badges357 bronze badges
126k6 gold badges192 silver badges357 bronze badges
4
Oh, an answer of @marmot that does not include anything from TikZ!?! I MUST READ IT.
– manooooh
Jul 28 at 0:05
1
@manooooh This is a great solution and also compact. I wish I could select two accepted answers. Can this be used inside afpeval
? Thanks for your time.
– AFP
Jul 28 at 0:40
3
@AFP No, it cannot because it isn't expandable (@for
isn't expandable because it does assignments, andmembertrue
andmemberfalse
are also assignments, so not expandable). The expandability ofl3fp
allows you to use it virtually anywhere TeX expects a number (see this trick, for example). The downside of this expandability is that everything inside an expression must be expandable too.
– Phelype Oleinik
Jul 28 at 2:19
add a comment |
4
Oh, an answer of @marmot that does not include anything from TikZ!?! I MUST READ IT.
– manooooh
Jul 28 at 0:05
1
@manooooh This is a great solution and also compact. I wish I could select two accepted answers. Can this be used inside afpeval
? Thanks for your time.
– AFP
Jul 28 at 0:40
3
@AFP No, it cannot because it isn't expandable (@for
isn't expandable because it does assignments, andmembertrue
andmemberfalse
are also assignments, so not expandable). The expandability ofl3fp
allows you to use it virtually anywhere TeX expects a number (see this trick, for example). The downside of this expandability is that everything inside an expression must be expandable too.
– Phelype Oleinik
Jul 28 at 2:19
4
4
Oh, an answer of @marmot that does not include anything from TikZ!?! I MUST READ IT.
– manooooh
Jul 28 at 0:05
Oh, an answer of @marmot that does not include anything from TikZ!?! I MUST READ IT.
– manooooh
Jul 28 at 0:05
1
1
@manooooh This is a great solution and also compact. I wish I could select two accepted answers. Can this be used inside a
fpeval
? Thanks for your time.– AFP
Jul 28 at 0:40
@manooooh This is a great solution and also compact. I wish I could select two accepted answers. Can this be used inside a
fpeval
? Thanks for your time.– AFP
Jul 28 at 0:40
3
3
@AFP No, it cannot because it isn't expandable (
@for
isn't expandable because it does assignments, and membertrue
and memberfalse
are also assignments, so not expandable). The expandability of l3fp
allows you to use it virtually anywhere TeX expects a number (see this trick, for example). The downside of this expandability is that everything inside an expression must be expandable too.– Phelype Oleinik
Jul 28 at 2:19
@AFP No, it cannot because it isn't expandable (
@for
isn't expandable because it does assignments, and membertrue
and memberfalse
are also assignments, so not expandable). The expandability of l3fp
allows you to use it virtually anywhere TeX expects a number (see this trick, for example). The downside of this expandability is that everything inside an expression must be expandable too.– Phelype Oleinik
Jul 28 at 2:19
add a comment |
Thanks for contributing an answer to TeX - LaTeX Stack Exchange!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2ftex.stackexchange.com%2fquestions%2f501773%2fchecking-if-an-integer-is-a-member-of-an-integer-list%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
1
I think an answer to one of my questions might be helpful here: tex.stackexchange.com/a/496671/85504
– MarcinKonowalczyk
Jul 27 at 23:11