numberOfButtons =
ToExpression@StringCases[ data[[ gln + 3]], DigitCharacter]
gives me this {2}
numberOfTopics =
ToExpression@StringCases[ data[[ topicNumberLine]], DigitCharacter]
gives me this {{1}}
I need to have numberOfTopics and numberOfButtons in the form of simple integers rather than embedded in a list
How do I do this ?
I do apologize for how basic this question is, but it is very hard to find out how to do simple things in Mathematica. Just look at how convoluted getting a number out of a string is.
Hi Lewis,
There are many ways to do this. One way
button = "There are 314 buttons";
button // StringCases[d : DigitCharacter .. :> ToExpression[d]] // Flatten // First
(* 314 *)
Thanks Rohit:
Figured it out on my own, but it wasn’t obvious
In[216]:= numberOfButtons =
ToExpression@StringCases[ data[[ gln + 3]], DigitCharacter]
Out[216]= {2}
The following should have worked but didn’t
In[217]:=
numberOfButtons[[1]] =
ToExpression@StringCases[ data[[ gln + 3]], DigitCharacter]
Out[217]= {2}
But this did
In[222]:= numberOfButtons[[1]]
Out[222]= 2
In[223]:= Head[numberOfButtons[[1]] ]
Out[223]= Integer
That seems pretty convoluted.
Once again, thanks for your help.
It seems “pretty convoluted” because built-in functions are designed to handle the general case, not just a very specific case. The language would be pretty limiting otherwise. What if the string had more than one integer?
button = "There are 314 buttons, 10 are green and 20 are blue";
button // StringCases[d : DigitCharacter .. :> ToExpression[d]]
(* {314, 10, 20} *)
That is why it returns a List of the matches. You can then extract whichever number you need using Part.
If you just need to handle a specific case of extracting one integer then write a function to do that.
(* Returns the first one by default *)
extractInteger[s_String, position_Integer : 1] :=
s // StringCases[d : DigitCharacter .. :> ToExpression[d]] //
Flatten // Part[#, position] &
extractInteger[button]
(* 314 *)
extractInteger[button, 3]
(* 20 *)
Rohit:
You are absolutely right about the generality. It wasn’t needed because of the metadata embedded in what I’m trying to do. I didn’t know about extracting strings when I initially wrote the question. Consider the first line in the file named "Cards 4550 to 4555 "
Total Number of Cards = 6
It is the first of 101 strings in the file
By the way I set up the metadata I know that the 6th word in the string will be a series of decimal digits telling me the number of cards, so the generality that I initially asked for wasn’t needed
So using
blix = StringExtract ["Total Number of Cards = 6 "]
Head[blix] gives String
blix = ToExpression [blix]
also gives blix
but Head[blix] now gives Integer
As always thanks for your help and insights.
LR
StringExtract requires 2 arguments. This fails to evaluate
StringExtract ["Total Number of Cards = 6 "]
Assuming
blix = "Total Number of Cards = 6 "
This
ToExpression[blix]
fails with “Set::write: Tag Times in Cards Number of Total is Protected.” Because it is equivalent to evaluating
Total Number of Cards = 6
Total and Number are built-in functions, space between symbols is interpreted as Times. It also has the side effect of creating symbols named of and Cards.
Lesson: Beware of evaluating arbitrary strings using ToExpression. The extractInteger function I suggested earlier is the safe way to do it because ToExpression is only evaluated on a string of DigitCharacter.
Rohit:
You are right of course and here is the way it should look
In[250]:= data[[ 1]]
Out[250]= "Total Number of Cards = 6 "
(* BEGIN PROLOGUE to do a bunch of cards
The variable data has been set up above. data is a list of 101strings *)
numCards = StringExtract [ data[[1]], 6 ]
"6"
In[295]:= Head[numCards]
Out[295]= String
In[296]:= numCards = ToExpression [numCards ]
Out[296]= 6
In[297]:= Head [ numCards ]
Out[297]= Integer
Because of the way the metaData is set up I know where the integers are to be found in each metaData string. Otherwise ToExpression wouldn’t work.
Thanks again.
LR
This will only work if the string contains 6.
StringExtract [ data[[1]], 6 ]
Presumably, you want general purpose code that can extract the number of cards rather than changing the code each time based on manually inspecting the data and changing 6 to something else.
No. Currently the cards reside in a variety of files each containing a variable number of cards. Most have 1,000, but I have made several containing 1, 5, 10, 25, 50, 100 cards for purposes of testing the Mathematica programs I’m in the process of developing.
The first string in each file has exactly 6 words, no more no less, the last of which is a bunch of digits, so
StringExtract [ data [[1]], 6 ] does exactly what I want.