Javascript中是否有切片的替代方法?

2024-04-18前端开发问题
5

本文介绍了Javascript中是否有切片的替代方法?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着跟版网的小编来一起学习吧!

问题描述

我正在使用数组进行计算器项目.我想让用户在找到答案之前编写多个函数,类似于 Casio fx-300ES Plus.现在我正在研究乘法,然后再转向其他运算符.为此,我认为最好的方法是使用 for 循环找到所有x"所在的索引,然后运行另外两个 for 循环,一个查看运算符的左侧,另一个查看右侧其中.一旦它找到另一个运算符,它将中断.然后我可以使用 slice() 将信息存储在x"旁边.

I am working on a calculator project using an array. I wanted to allow the user to write multiple functions before finding the answer, similar to a Casio fx-300ES Plus. Right now I am working on multiplication before moving to other operators. To do this I thought the best way is to find the index at which all 'x' are located using a for-loop, then run two other for-loops, one looking at the left of the operator, the other looking at the right of it. Once it finds another operator, it will break. I could then store the information next to the 'x' using slice().

我遇到的问题是当运算符之间的数字为 1 时.如果我使用 slice() 它不起作用,因为索引之间没有信息.还有其他方法可以将这些数字存储到数组中吗?

The problem I have run in to is when the numbers between operators is 1. If I use slice() it does not work as there is no information between the indexes. Is there another way to store these numbers into an array?

非常感谢任何有关这方面的信息.

Any information on this is much appreciated.

var array = ['7', '3', '+', '6', 'x', '8', '+', '5', '4', 'x', '2'];

    //for loop checking for 'x' symbols
    for (var i = 0; i < array.length; i++){
        console.log("i " + array[i]);
        //if there is an 'x'
        if (array[i] == 'x') {
            console.log('index is at ' + i);
            //create an array to eventually store the values
            var newArray = new Array();
                //checks for the index where j is NaN on the LEFT side
                for (j = i - 1; j > 0; --j){
                    if (isNaN(array[j])){
                        console.log('j is ' + j);
                        break;
                    }
                }  
                //checks for the index where e is NaN on the RIGHT side
                for (e = i + 1; e < array.length; e++)
                {
                    if (isNaN(array[e])){
                        console.log('e is at ' + e);
                        break;
                    } else if (e == array.length - 1) {
                        console.log('e is at array length of ' + e);
                        break;
                    }
                }
              //add the numbers between j and i to newArray
              newArray = array.slice(j + 1, i);
                        console.log(newArray);
              //add the numbers between i and e to newArray
              newArray = array.slice(i + 1, e);
                        console.log(newArray);  
              console.log("array of slice is " + newArray);
        }
    }

推荐答案

您可以编写 tokenize 来消耗您的文本输入并生成令牌流 -

You could write tokenize which consumes your text input and produces a stream of tokens -

const input = 
  [ '7', '3', '+', '6', 'x', '8', '+', '5', '4', 'x', '2' ]
  
function* tokenize (es) {
  let r = 0, n
  for (const e of es) {
    switch (e) {
      case "+":
      case "x":
        yield { number: r }
        yield { operation: e }
        r = 0
        break
      default:
        n = Number.parseInt(e, 10)
        if (Number.isNaN(n))
          throw Error(`unexpected input: ${e}`)
        else
          r = r * 10 + n
        break
    }
  }
  if (r > 0) yield { number: r }
}
          
for (const t of tokenize(input))
  console.log(t)

{"number":73}
{"operation":"+"}
{"number":6}
{"operation":"x"}
{"number":8}
{"operation":"+"}
{"number":54}
{"operation":"x"}
{"number":2}

随后是 parse,它使用一个标记流并生成一个抽象语法树 -

Followed by parse which consumes a stream of tokens and produces a abstract syntax tree -

function parse (ts) {
  let s = e => e
  for (const t of ts) {
    if (t?.number) {
      let r = s(t)
      s = _ => r
    }
    else if (t?.operation) {
      let left = s()
      s = right => ({ operation: t.operation, left, right })
    }
    else {
      throw Error(`unexpected token: ${JSON.stringify(t)}`)
    }
  }
  return s()
}

console.log(parse(tokenize(input)))

{
  operation: "x",
  left: {
    operation: "+",
    left: {
      operation: "x",
      left: {
        operation: "+",
        left: { number: 73 },
        right: { number: 6 }
      },
      right: { number: 8 }
    },
    right: { number: 54 }
  },
  right: { number: 2 }
}

最后是 eval,它将语法树评估为程序 -

Finally eval which evaluates the syntax tree as a program -

function eval (e) {
  if (e?.number)
    return e.number
  else if (e?.operation)
    return evalOp(e)
  else
    throw Error(`unexpected expression: ${JSON.stringify(e)}`)
}

我们通过单独编写 evalOp 来简化 eval.这种技术被称为相互递归,对于遍历树状结构非常有效 -

We simplify eval by writing evalOp separately. This technique is known as mutual recursion and is super effective for traversing tree-like structures -

function evalOp (e) {
  switch (e?.operation) {
    case "+": return eval(e.left) + eval(e.right)
    case "x": return eval(e.left) * eval(e.right)
    default: throw Error(`unexpected operation: ${e.operation}`)
  }
}

tokenizeparseeval 放在一起计算结果 -

Bring tokenize, parse, and eval together to compute the result -

const input = 
  [ '7', '3', '+', '6', 'x', '8', '+', '5', '4', 'x', '2' ]

console.log(eval(parse(tokenize(input))))

1372

当使用袖珍计算器的运算顺序进行评估时,这是正确的 -

This is correct when evaluated using pocket calculator order of operations -

73 
... + 6 = 79
... * 8 = 632
... + 54 = 686
... * 2 = 1372

如果您想使用不同的操作顺序(即 PEMDAS)进行评估,则必须重写 parse 以将令牌流解释为不同的程序.

If you wanted to evaluate using a different order of operations, ie PEMDAS, you would have to rewrite parse to interpret the stream of tokens as a different program.

展开下面的代码片段以在您的浏览器中验证结果 -

Expand the snippet below to verify the result in your browser -

const input = 
  [ '7', '3', '+', '6', 'x', '8', '+', '5', '4', 'x', '2' ]

function* tokenize (es) {
  let r = 0, n
  for (const e of es) {
    switch (e) {
      case "+":
      case "x":
        yield { number: r }
        yield { operation: e }
        r = 0
        break
      default:
        n = Number.parseInt(e, 10)
        if (Number.isNaN(n))
          throw Error(`unexpected input: ${e}`)
        else
          r = r * 10 + n
        break
    }
  }
  if (r > 0) yield { number: r }
}

function parse (ts) {
  let s = e => e
  for (const t of ts) {
    if (t?.number) {
      let r = s(t)
      s = _ => r
    }
    else if (t?.operation) {
      let left = s()
      s = right => ({ operation: t.operation, left, right })
    }
    else {
      throw Error(`unexpected token: ${JSON.stringify(t)}`)
    }
  }
  return s()
}

function eval (e) {
  if (e?.number)
    return e.number
  else if (e?.operation)
    return evalOp(e)
  else
    throw Error(`unexpected expression: ${JSON.stringify(e)}`)
}

function evalOp (e) {
  switch (e?.operation) {
    case "+": return eval(e.left) + eval(e.right)
    case "x": return eval(e.left) * eval(e.right)
    default: throw Error(`unexpected operation: ${e.operation}`)
  }
}

console.log(eval(parse(tokenize(input))))

这篇关于Javascript中是否有切片的替代方法?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持跟版网!

The End

相关推荐

js删除数组中指定元素的5种方法
在JavaScript中,我们有多种方法可以删除数组中的指定元素。以下给出了5种常见的方法并提供了相应的代码示例: 1.使用splice()方法: let array = [0, 1, 2, 3, 4, 5];let index = array.indexOf(2);if (index -1) { array.splice(index, 1);}// array = [0,...
2024-11-22 前端开发问题
182

JavaScript小数运算出现多位的解决办法
在开发JS过程中,会经常遇到两个小数相运算的情况,但是运算结果却与预期不同,调试一下发现计算结果竟然有那么长一串尾巴。如下图所示: 产生原因: JavaScript对小数运算会先转成二进制,运算完毕再转回十进制,过程中会有丢失,不过不是所有的小数间运算会...
2024-10-18 前端开发问题
301

JavaScript(js)文件字符串中丢失"\"斜线的解决方法
问题描述: 在javascript中引用js代码,然后导致反斜杠丢失,发现字符串中的所有\信息丢失。比如在js中引用input type=text onkeyup=value=value.replace(/[^\d]/g,) ,结果导致正则表达式中的\丢失。 问题原因: 该字符串含有\,javascript对字符串进行了转...
2024-10-17 前端开发问题
437

layui中table列表 增加属性 edit="date",不生效怎么办?
如果你想在 layui 的 table 列表中增加 edit=date 属性但不生效,可能是以下问题导致的: 1. 缺少日期组件的初始化 如果想在表格中使用日期组件,需要在页面中引入 layui 的日期组件,并初始化: script type="text/javascript" src="/layui/layui.js"/scrip...
2024-06-11 前端开发问题
455

Rails/Javascript:如何将 rails 变量注入(非常)简单的 javascript
Rails/Javascript: How to inject rails variables into (very) simple javascript(Rails/Javascript:如何将 rails 变量注入(非常)简单的 javascript)...
2024-04-20 前端开发问题
5

CoffeeScript 总是以匿名函数返回
CoffeeScript always returns in anonymous function(CoffeeScript 总是以匿名函数返回)...
2024-04-20 前端开发问题
13