【问题标题】:How do I determine if a String is an Array?如何确定字符串是否为数组?
【发布时间】:2020-03-12 00:18:03
【问题描述】:

给定一个像"['chad', 123, ['tankie'], '!!!']" 这样的字符串,我需要返回一个布尔值来说明这个字符串是否是一个有效的数组。

我对大多数解决方案持开放态度,包括正则表达式。

【问题讨论】:

  • 我不寒而栗,但是eval()呢?
  • 你给定的字符串实际上不是一个数组。这需要字符串 chad 以单引号结尾。
  • 字符串总是一个数组——一个字符数组。如果您的意思是内容可以是一个数组,例如 JSON 数组,那么您需要定义将字符串的内容变成可以解析为对象数组的规则。
  • 如果您只接受有效的 JSON(双引号),使用 JSON.parse() 会更容易。如果无效,它将引发错误,您可以捕获该错误以返回 false。如果您需要接受您提供的输入作为示例,eval() 也很简单,但根据您的用例(例如"[alert('P0wned!')]")并不安全。是否所有项目都应该具有原始类型?
  • 如果它是有效的Javascript,你应该能够用双引号替换单引号,并解析为JSON等。

标签: javascript arrays regex string typescript


【解决方案1】:

也许它对其他人有用,您也可以这样做,并且只需几行。如果你在'a'中定义你想要分析的字符串

a = "['chad', 123, ['tankie'], '!!!']";
Array.isArray( JSON.parse( a.replace(/'/g,'"') ) );

这将返回真或假

【讨论】:

    【解决方案2】:

    您不应该使用 eval(出于代码注入的明显原因)。当然,我将要做的解析为 JSON 与数组不同,但它是不使用 eval() 时最接近的结果。

    您可以使用JSON.parse 方法。这里唯一的缺点是,由于 JSON 的限制,所有字符串必须用双引号 (") 分隔。

    使用 nodejs 解释器的快速示例:

    > var arrayString = '["chad", 123, ["tankie"], "!!!"]';
    undefined
    > JSON.parse(arrayString);
    [ 'chad', 123, [ 'tankie' ], '!!!' ]
    > var notArrayString = 'asdas!asd1{}1239]1[';
    undefined
    > JSON.parse(notArrayString);
    Thrown:
    SyntaxError: Unexpected token a in JSON at position 0
    > 
    

    然后您可以使用Array.isArray 方法来检查它是否是一个数组。

    function stringIsArray(str) {
        try {
            return Array.isArray(JSON.parse(str));
        } catch (e) {
            return false;
        }
    }
    
    stringIsArray('["chad", 123, ["tankie"], "!!!"]'); // returns true
    stringIsArray('something else, not an array'); // returns false
    

    如果您不关心引号,可以添加str.replace('\'', '"')

    【讨论】:

      【解决方案3】:

      假设您想要支持 Javascript 语法的某个子集,您可以使用正则表达式来删除空格和标量文字,然后检查剩余的内容是否与嵌套模式 [,[,,,],,,] 匹配。

      let remove = [
          /\s+/g,
          /'(\\.|[^'])*'/g,
          /"(\\.|[^"])*"/g,
          /\d+/g,
      ];
      
      let emptyArray = /\[,*\]/g;
      
      function stringIsArray(str) {
      
          for (let r of remove)
              str = str.replace(r, '');
      
          if (str[0] !== '[')
              return false;
      
          while (str.match(emptyArray))
              str = str.replace(emptyArray, '');
      
          return str.length === 0;
      }
      
      console.log(stringIsArray("'abc'"));
      console.log(stringIsArray(`['abc', ['def', [123, 456], 'ghi',,],,]`));
      console.log(stringIsArray(String.raw`
                ['a"b"c', ["d'e'f", 
           [123, [[   [[["[[[5]]]"]]]]], 456], '\"\'""""',,],,]
      `));

      如果您希望 所有 Javascript 语法得到支持(例如,包含包含数组的对象的数组等),您需要一个真正的解析器。我编写了一个名为 litr 的模块,它正是这样做的——评估 javascript 文字,所有这些:

      const litr = require('litr'); // or <script src=litr.js>
      
      myJsObject = litr.parse(myString);
      console.log('is Array?', Array.isArray(myJsObject))
      

      基本上,它是一个围绕 PEG.js javascript 语法的薄包装器。

      【讨论】:

      • 你为什么改变你的答案?
      • 这有很好的元素,比如解析引用的东西。但是,编译时常量文字可能包含的内容超出了仅与 \d 匹配的内容。示例包括浮点数、指数、符号、数学运算符号、字符串连接等。我猜布尔值的真/假也是如此。
      • @x15:见答案的第二部分。
      • 是的,我明白了。看本土的东西来做这种事情有点困难。
      • @x15:不知道你的意思,无论如何,谢谢你的意见。
      【解决方案4】:

      如果您需要支持“任何”字符串,您可以使用new Function() 作为eval() 更安全的替代方案。 [source]

      function stringIsArray(str) {
        try {
          return new Function(`return Array.isArray(${str})`)();
        } catch {
          return false;
        }
      }
      
      console.log(stringIsArray("abc"));
      console.log(stringIsArray("['chad', 123, ['tankie'], '!!!']"));

      【讨论】:

      • ['c"h"ad', "1'2'3", 't\\"ankie'] 等怎么样?
      • @georg 我添加了一个替代方案。
      • new Functioneval 基本上是一回事。尽管 MDN 页面上说了什么,但它们在安全性或性能方面没有区别。当然,两者都解决了 OP 的直接问题(如果他们足够小心的话)。
      • @georg 嗯,我认为“基本上相同的事情”有点夸大其词(e.g.),尽管同意两者都需要一些预先考虑,因为它与风险/利用有关。话虽如此,我确实认为像您这样的方法 - 使用严格的字符串操作 - 是 OP 的最佳选择。
      【解决方案5】:
      let strtotest = "['chad', 123, ['tankie'], '!!!']"
      Array.isArray(eval(strtotest))
      

      如果数组有效,这将返回 true。 如果字符串中的语法不正确,它也会抛出错误,所以你也必须处理它。

      我想指出 eval 是一个你永远不应该使用的可怕的东西,但是看到这个问题的要求很疯狂,我认为这个解决方案是合适的。

      【讨论】:

      • > 但是看到这个问题的要求很疯狂,我认为这个解决方案很合适。您对这里处理的数据了解多少?
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-06-25
      相关资源
      最近更新 更多