Mathjs: Disable the parser's zero-based to one-based arrays transform

Created on 24 Jan 2017  Â·  11Comments  Â·  Source: josdejong/mathjs

Hi, thanks for the great library !

Is there a way to switch from one-based arrays to zero based array in math's parser ?

question

All 11 comments

There is no configuration option for this but you could achieve so by overriding the set of functions that the expression parser uses math.expression.transform with the plain JS functions math:

// see the one-based behavior of the expression parser
console.log(math.eval('A[1]', {A: [1,2,3]}))   // 1

// see what functions have transforms
console.log(Object.keys(math.expression.transform))
// ["concat", "filter", "forEach", "index", "map", "max", "mean", "min", "range", "subset"]

// replace the object with `transformed` functions for an empty one
math.expression.transform = Object.create(math)

// the expression parser now has zero-based behavior:
console.log(math.eval('A[1]', {A: [1,2,3]}))   // 2

One caveat is that when you would import a new function after this change and this function comes with it's own transform, it will be added to math.expression.transform, so after an import you have to replace the transform object again.

Awesome, thanks a lot !

Le 24/01/2017 à 20:39, Jos de Jong a écrit :
>

There is no configuration option for this but you could achieve so by
overriding the set of functions that the expression parser uses
|math.expression.transform| with the plain JS functions |math|:

// see the one-based behavior of the expression parser
console.log(math.eval('A[1]', {A: [1,2,3]}))// 1

// see what functions have transforms
console.log(Object.keys(math.expression.transform))
// ["concat", "filter", "forEach", "index", "map", "max", "mean",
"min", "range", "subset"]

// replace the object with transformed functions for an empty one
math.expression.transform = Object.create(math)

// the expression parser now has zero-based behavior:
console.log(math.eval('A[1]', {A: [1,2,3]}))// 2

One caveat is that when you would import a new function after this
change and this function comes with it's own transform, it will be
added to |math.expression.transform|, so after an import you have to
replace the transform object again.

—
You are receiving this because you authored the thread.
Reply to this email directly, view it on GitHub
https://github.com/josdejong/mathjs/issues/782#issuecomment-274914139,
or mute the thread
https://github.com/notifications/unsubscribe-auth/AFBJZ_se4QYtTmPdFmEjtwHy1FzalqTzks5rVlNYgaJpZM4Lsewk.

:+1: you're welcome

Is this still supposed to be true ? Seems like the trick isn't working anymore.

Good point, there have been some internal refactorings. To achieve the same in the latest versions of mathjs, you can do the following:

// see the one-based behavior of the expression parser
console.log(math.eval('A[1]', {A: [1,2,3]}))   // 1

// see what functions have transforms
console.log(Object.keys(math.expression.transform))
// ["concat", "filter", "forEach", "index", "map", "max", "mean", "min", "range", "subset"]

// replace the object containing regular and transformed functions for an object with
// just regular functions. If needed , you can restore orginal behavior afterwards by 
// merging the functions in math.expression.transform again 
// in math.expression.mathWithTransform
math.expression.mathWithTransform = Object.assign({}, math)

// the expression parser now has zero-based behavior:
console.log(math.eval('A[1]', {A: [1,2,3]}))   // 2

Awesome, thank you !

@josdejong :'( Looks like this trick is once again no longer working? Got an update?

Ah, yes indeed that doesn't work anymore since v6 I think. I will see if there is another workaround.

@wes-r this should be easier now in v6, however, I noticed that IndexNode currently uses a hard-coded, one-based instance of the index function. I've addressed this in b9175a1a29e9b9ac02c899e956551c14c7ccd110 (not yet published).

After this fix is published, it's simply a matter of cherry picking which functions you want to import, in your case that is all functions except transforms:

import { create, all } from 'mathjs'

// default, one-based indices:
const math = create(all)
console.log(math.evaluate('A[1]', { A: [1, 2, 3] })) // 1


// filter transform functions out of the imports:
const allButTransforms = {}
Object.keys(all)
  .filter(key => !key.endsWith('Transform'))
  .forEach(key => {
    allButTransforms[key] = all[key]
  })
// Alternatively using lodash:
//   const allButTransforms = pickBy(all, (value, key) => !key.endsWith('Transform'))

// custom zero-based indices:
const mathWithoutTransforms = create(allButTransforms)
console.log(mathWithoutTransforms.evaluate('A[1]', { A: [1, 2, 3] })) // 2

I will let you know as soon as this fix is published.

Ok should be fixed now in [email protected], can you give it a try Wesley?

Success! TY!

Was this page helpful?
0 / 5 - 0 ratings

Related issues

lwirtz picture lwirtz  Â·  3Comments

zzzgit picture zzzgit  Â·  4Comments

smith120bh picture smith120bh  Â·  4Comments

Lakedaemon picture Lakedaemon  Â·  5Comments

hogegex picture hogegex  Â·  3Comments