How to Substitute Symbols in a Language Object

Replace characters in R objects of class 'expression'

1) substitute Convert to a call object, use substitute on that and then convert back (or maybe a call object is sufficient for your needs and you don't need to convert back to expression). This works entirely at the R language level as opposed to string manipulation.

as.expression(do.call("substitute", list(exp[[1]], list(T = as.name("I")))))
## expression(italic(N[I]))

2) recurse An alternative is to recusively walk through the call object and replace T with I. Note that this inputs and outputs a call object so convert from expression to call object and from call object to expression if you need to work with expression objects rather than call objects.

T2I <- function(e) {
if (identical(e, as.name("T"))) e <- as.name("I")
else if (length(e) > 1) for(i in 1:length(e)) e[[i]] <- Recall(e[[i]])
e
}

as.expression(T2I(exp[[1]]))
## expression(italic(N[I]))

3) assignment If you know the structure of exp then this assignment will work:

exp.orig <- exp # in case you need to save the original

exp[[1]][[2]][[3]] <- as.name("I")
exp
## expression(italic(N[I]))

4) string manipulation This one converts to a character string, performs replacement and converts back. It is similar to another answer but not exactly the same:

parse(text = gsub("\\bT\\b", "I", format(exp[[1]])))
## expression(italic(N[I]))

5) rrapply The rrapply function in the rrapply package can walk an expression and perform replacements.

library(rrapply)
condition <- function(x) x == as.name("T")
f <- function(x) as.name("I")
rrapply(exp, condition = condition, f = f, how = "replace")
## expression(italic(N[I]))

UPDATES

Added rrapply solution.

How to substitute values in SymPy object?

To substitute values, you can use subs with a dictionary mapping each variable to its value.

Note that using sy.Integer(1) or similar expressions is only needed when working with fractions of constants, to avoid that Python converts those fractions to floats before sympy can get its grip on it.

import sympy as sy

a, b, c = sy.symbols('a, b, c', real = True)
A = sy.Matrix([[1, 2, -3, a], [4, -1, 8, b], [2, -6, -4, c]])
A_rref = A.rref()
print(A_rref[0].subs({a: 3, b: 6, c: 7}))

Output:

Matrix([[1, 0, 0, 31/14],
[0, 1, 0, -16/91],
[0, 0, 1, -69/182]])

To find out about how sympy expressions are built up, srepr comes in handy:

print(sy.srepr(A_rref[0][0,3]))

Which gives:

Add(Mul(Rational(2, 7), Symbol('a', real=True)), Mul(Rational(1, 7), Symbol('b', real=True)), Mul(Rational(1, 14), Symbol('c', real=True)))

So, the expression is a tree of sub expressions. At the highest level, there is a sum, so that's what's shown when printing the type. This post contains some code to draw the expression tree as a text diagram:

    +---> symbol Rational(1, 7)
|
+---> symbol Symbol('b', real=True)
|
+---+ function <class 'sympy.core.mul.Mul'> had 2 arguments
|
| +---> symbol Rational(1, 14)
| |
| +---> symbol Symbol('c', real=True)
| |
+---+ function <class 'sympy.core.mul.Mul'> had 2 arguments
|
| +---> symbol Rational(2, 7)
| |
| +---> symbol Symbol('a', real=True)
| |
+---+ function <class 'sympy.core.mul.Mul'> had 2 arguments
|
+ function <class 'sympy.core.add.Add'> had 3 arguments

Replace language specific characters in python with English letters

Try unidecode:

# coding=utf-8
from unidecode import unidecode

city = "České Budějovice"
print(unidecode(city))

Prints Ceske Budejovice as desired (assuming your post has a typo).

Note: if you're using Python 2.x, you'll need to decode the string before passing it to unidecode, e.g. unidecode(city.decode('utf-8'))

String replace between symbols?

One way would go from the string to the data object instead of looping through all the keys.

var myDataObject = {
name : 'Nikola Tesla',
birth : ['10 July 1856','10. Juli 1856'],
nation : ['Serbian','Serbisch'],
knownFor : ['Alternating current',' Zweiphasenwechselstrom']
};
var englishStr = "#name#, born #birth[1]# , #nation[1]# best known for his contributions to #knownFor[1]#";

var re = /#([^\[#]+)\[?(\d+)?\]?#/; //Looks for #STRING# or #STRING[NUMBER]#
var test;
while ( (test=re.exec(englishStr))!==null) { //Keep looking for matches in the string
var key = test[1]; //get the key to the object
var index = test[2]; //get the index if there
var item = myDataObject[key]; //get reference to the item in the object
if (index!==undefined && item) { //if we have an index, look up the value from array
index = parseInt(index,10)-1; //arrays are zero index, so need to subtract one
item = item[index]; //get the string
}
englishStr = englishStr.replace(re, item || "N/A"); //make the replacement in the string with the data from the object
};

How to handle  (object replacement character) in URL

I found the issue resolved by just replacing URLs with this symbol because there are other URLs with Unicode symbols that were invisible that couldnt be converted ect..

So I just compared the urls to the following regex if it returns false then I just bypass it. Hope this helps someone out:

boolean newURL = url.matches("^[a-zA-Z0-9_:;/.&|%!+=@?-]*$");

Substitute the ^ (power) symbol with C's pow syntax in mathematical expression

Here is a solution that follows the parse tree recursively and replaces ^:

#parse the expression
#alternatively you could create it with
#expression(((2-x+3)^2+(x-5+7)^10)^0.5)
e <- parse(text = "((2-x+3)^2+(x-5+7)^10)^0.5")

#a recursive function
fun <- function(e) {
#check if you are at the end of the tree's branch
if (is.name(e) || is.atomic(e)) {
#replace ^
if (e == quote(`^`)) return(quote(pow))
return(e)
}
#follow the tree with recursion
for (i in seq_along(e)) e[[i]] <- fun(e[[i]])
return(e)
}

#deparse to get a character string
deparse(fun(e)[[1]])
#[1] "pow((pow((2 - x + 3), 2) + pow((x - 5 + 7), 10)), 0.5)"

This would be much easier if rapply worked with expressions/calls.

Edit:

OP has asked regarding performance. It is very unlikely that performance is an issue for this task, but the regex solution is not faster.

library(microbenchmark)
microbenchmark(regex = {
v <- "((2-x+3)^2+(x-5+7)^10)^0.5"
x <- grepl("(\\(((?:[^()]++|(?1))*)\\))\\^(\\d*\\.?\\d+)", v, perl=TRUE)
while(x) {
v <- sub("(\\(((?:[^()]++|(?1))*)\\))\\^(\\d*\\.?\\d+)", "pow(\\2, \\3)", v, perl=TRUE);
x <- grepl("(\\(((?:[^()]++|(?1))*)\\))\\^(\\d*\\.?\\d+)", v, perl=TRUE)
}
},
BrodieG = {
deparse(f(parse(text = "((2-x+3)^2+(x-5+7)^10)^0.5")[[1]]))
},
Roland = {
deparse(fun(parse(text = "((2-x+3)^2+(x-5+7)^10)^0.5"))[[1]])
})

#Unit: microseconds
# expr min lq mean median uq max neval cld
# regex 321.629 323.934 335.6261 335.329 337.634 384.623 100 c
# BrodieG 238.405 246.087 255.5927 252.105 257.227 355.943 100 b
# Roland 211.518 225.089 231.7061 228.802 235.204 385.904 100 a

I haven't included the solution provided by @digEmAll, because it seems obvious that a solution with that many data.frame operations will be relatively slow.

Edit2:

Here is a version that also handles sqrt.

fun <- function(e) {    
#check if you are at the end of the tree's branch
if (is.name(e) || is.atomic(e)) {
#replace ^
if (e == quote(`^`)) return(quote(pow))
return(e)
}
if (e[[1]] == quote(sqrt)) {
#replace sqrt
e[[1]] <- quote(pow)
#add the second argument
e[[3]] <- quote(0.5)
}
#follow the tree with recursion
for (i in seq_along(e)) e[[i]] <- fun(e[[i]])
return(e)
}

e <- parse(text = "sqrt((2-x+3)^2+(x-5+7)^10)")
deparse(fun(e)[[1]])
#[1] "pow(pow((2 - x + 3), 2) + pow((x - 5 + 7), 10), 0.5)"

substitute values and then output an expression

This can be surprisingly tricky, and depends a bit on how your equation is stored.

If you don't need to store the equation (expression) in a symbol, this is not too bad:

f <- function(a,b) { bquote(.(a)+.(b)*x) }
f(2,4)
## 2 + 4 * x

If you have ee <- expression(a+b*x), then you can use this answer to get to

L <- list(a=2,b=4)
do.call(substitute, list(ee[[1]], L))
## or substituteDirect(ee[[1]], L)
## 2 + 4 * x

(I'm not 100% sure why you have to use [[1]] to extract the "body" of the expression, but you do.)

If you want to do this with multiplication denoted by juxtaposition (i.e. interpreting a+bx as a+b*x) that's going to be much harder ...

How to replace duplicate characters in a string - Javascript

Your current code is looking for the first matching letter exclusively. In one way or another, you'll need a loop to handle duplicate characters.

But I'd suggest another modification: rather than keeping track of the 'progress mask', you should maintain the list of all letters (good or wrong) that have been tried so far.

Having secretWord and progress is not providing enough information to detect wrong letters that have been already tried -- which is probably a feature that you eventually want to have implemented. On the other hand, you can quickly rebuild progress each time you need it by using secretWord and the list of tried letters.

Let's say that tried letters are stored in the letters string. Then progress can be computed either with an explicit loop such as:

// classic for loop
for(i = 0, progress = ''; i < secretWord.length; i++) {
progress += letters.indexOf(secretWord[i]) == -1 ? '_' : secretWord[i]
}

or an implicit loop such as:

// functional programming
progress = secretWord.split('').map(function(letter) {
return letters.indexOf(letter) == -1 ? '_' : letter;
}).join('');

or:

// regular expression: replace() with custom callback
progress = secretWord.replace(/./g, function(letter) {
return letters.indexOf(letter) == -1 ? '_' : letter;
});

or:

// regular expression: replace() without callback
progress = secretWord.replace(new RegExp('[^' + letters + ']', 'g'), '_');

Below is some example code showing the game logic with this approach.

var secretWord = 'apple',    letters    = '';
function play(letter) { if(letters.indexOf(letter) != -1) { console.log("You've already tried '" + letter + "' ..."); } else { letters += letter;
if(secretWord.indexOf(letter) == -1) { console.log(letter + ' -> wrong!'); } else { var progress = secretWord.replace(new RegExp('[^' + letters + ']', 'g'), '_');
console.log(letter + ' -> ' + progress); if(progress == secretWord) { console.log('Well done!'); } } }}
play('i');play('e');play('p');play('e');play('a');play('l');


Related Topics



Leave a reply



Submit