Replies: 3 comments 3 replies
-
I think you can use a regex, but you have to be careful to use word boundries and a case sensitive search. You can also parse the expression using |
Beta Was this translation helpful? Give feedback.
-
Alternatively, you can use resolve which is basically a variable substitution function, together with the flexible definition of what a "scope" is:
Note that you might be tempted by the much simpler
and that will seem to work, but it will produce a re-entrant mathjs expression in which all of the occurrences of |
Beta Was this translation helpful? Give feedback.
-
@josdejong @gwhitney Thank you for the suggestions. I started working on this using the Related question: In the past, I had to write a function that outputs all external parameters, as dependencies. This allowed me to scan though expressions that would need to be recomputed if one of their dependent variables changed. This is what ended up working great for us. Do you think it's overkill? /**
* Extracts variables used in the expression that are not locally defined.
* @private
* @param {MathNode} node - The parsed math expression tree node.
* @returns {Array<string>} A list of unique variable names found in the expression.
*/
private extractVariables(node: MathNode): Array<string> {
const variables: Array<string> = [];
const localVariables = new Set<string>();
const traverse = (currentNode: MathNode): void => {
if (isAssignmentNode(currentNode) && isSymbolNode(currentNode.object)) {
localVariables.add(currentNode.name);
traverse((currentNode as AssignmentNode).value);
} else if (isOperatorNode(currentNode)) {
for (const arg of currentNode.args) {
traverse(arg);
}
} else if (
isSymbolNode(currentNode) &&
!localVariables.has(currentNode.name)
) {
// don't interpret units like 'kg' as variables
try {
unit(currentNode.name);
} catch {
variables.push(currentNode.name);
}
} else if (isFunctionNode(currentNode) || isOperatorNode(currentNode)) {
for (const arg of currentNode.args) {
traverse(arg);
}
} else if (isParenthesisNode(currentNode)) {
traverse((currentNode as ParenthesisNode).content);
} else if (isBlockNode(currentNode)) {
for (const block of currentNode.blocks) {
traverse(block.node);
}
} else if (isAccessorNode(currentNode)) {
const variableName = currentNode.toString();
if (!localVariables.has(variableName)) {
variables.push(variableName);
}
} else if (isArrayNode(currentNode)) {
for (const item of currentNode.items) {
traverse(item);
}
}
};
traverse(node);
return Array.from(new Set(variables)); // Remove duplicates
} |
Beta Was this translation helpful? Give feedback.
-
I'm wondering if there is a handy function or code to rename multiple instances of a variable by name in an expression? This would work similar to
Rename Symbol
in VS Code.Beta Was this translation helpful? Give feedback.
All reactions