Message Boards Message Boards

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

Converting list to atom expression?

Posted 2 years ago
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.

POSTED BY: Lewis Robinson
8 Replies
Posted 2 years ago

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.

POSTED BY: Lewis Robinson
Posted 2 years ago

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

POSTED BY: Lewis Robinson
Posted 2 years ago

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.

POSTED BY: Rohit Namjoshi
Posted 2 years ago

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.

POSTED BY: Rohit Namjoshi
Posted 2 years ago

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

POSTED BY: Lewis Robinson
Posted 2 years ago

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 *)
POSTED BY: Rohit Namjoshi
Posted 2 years ago

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.

POSTED BY: Lewis Robinson
Posted 2 years ago

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 *)
POSTED BY: Rohit Namjoshi
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