【问题标题】:Create an array of characters from specified range从指定范围创建一个字符数组
【发布时间】:2012-09-04 19:20:45
【问题描述】:

我阅读了一些有人在 Ruby 中执行此操作的代码:

puts ('A'..'Z').to_a.join(',')

输出:

A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z

Javascript 中有什么东西可以让这件事变得同样简单吗?如果没有,是否有允许类似功能的 Node 模块?

【问题讨论】:

  • var arr=[]; for (var idx='A'.charCodeAt(0),end='Z'.charCodeAt(0); idx <=end; ++idx){arr.push(String.fromCharCode(idx));} arr.join();
  • 是的,我担心我需要使用 for 循环。
  • 如果您愿意,可以使用 while 循环;)
  • 看来我想要的是Javascript不支持的“范围”,尽管似乎很多其他语言都支持它。
  • [...Array(26).keys()].map( (_, i) => String.fromCharCode('A'.charCodeAt(0) + i) )

标签: javascript ruby node.js


【解决方案1】:

如果您使用的是 ES6,您可以使用Array.from() 生成一个序列,方法是传入一个类似数组的对象来获取范围的长度,并将一个 map 函数作为第二个参数来转换每个项目的数组键使用 String.fromCharCode() 在范围内转换成一个字符:

Array.from({ length: 26 }, (_, i) => String.fromCharCode('A'.charCodeAt(0) + i));

您还可以使用 Array 构造函数(注意:ES6 允许使用函数调用或 new 运算符调用构造函数)来初始化所需默认长度的数组,使用 Array.fill() 填充它,然后通过它映射:

Array(26).fill().map((_, i) => String.fromCharCode('A'.charCodeAt(0) + i));

spread operator 也可以做到这一点:

[...Array(26)].map((_, i) => String.fromCharCode('A'.charCodeAt(0) + i));

以上三个示例将返回一个包含从 A 到 Z 字符的数组。对于自定义范围,您可以调整长度和起始字符。

对于不支持 ES6 的浏览器,可以使用 babel-polyfill 或 core-js polyfill (core-js/fn/array/from)。

如果你的目标是 ES5,我会推荐Array.apply solution by @wires,它与这个非常相似。

最后,Underscore/Lodash 和 Ramda 有一个 range() 函数:

_.range('A'.charCodeAt(0), 'Z'.charCodeAt(0) + 1).map(i => String.fromCharCode(i));

【讨论】:

    【解决方案2】:

    Javascript 本身没有该功能。您可以在下面找到一些解决方法的示例:

    普通函数,来自基本平面的任何字符(不检查代理对)

    function range(start,stop) {
      var result=[];
      for (var idx=start.charCodeAt(0),end=stop.charCodeAt(0); idx <=end; ++idx){
        result.push(String.fromCharCode(idx));
      }
      return result;
    };
    
    range('A','Z').join();
    

    同上,但作为函数添加到数组原型中,因此可用于所有数组:

    Array.prototype.add_range = function(start,stop) {
      for (var idx=start.charCodeAt(0),end=stop.charCodeAt(0); idx <=end; ++idx){
        this.push(String.fromCharCode(idx));
      }
      return this;
    };
    
    [].add_range('A','Z').join();
    

    预选字符的范围。比上面的函数更快,并且让你用alphanum_range('A','z')来表示A-Z和a-z:

    var alphanum_range = (function() {
      var data = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'.split('');
      return function (start,stop) {
        start = data.indexOf(start);
        stop = data.indexOf(stop);
        return (!~start || !~stop) ? null : data.slice(start,stop+1);
      };
    })();
    
    alphanum_range('A','Z').join();
    

    或 ascii 范围内的任何字符。通过使用缓存数组,比每次构建数组的函数都要快。

    var ascii_range = (function() {
      var data = [];
      while (data.length < 128) data.push(String.fromCharCode(data.length));
      return function (start,stop) {
        start = start.charCodeAt(0);
        stop = stop.charCodeAt(0);
        return (start < 0 || start > 127 || stop < 0 || stop > 127) ? null : data.slice(start,stop+1);
      };
    })();
    
    ascii_range('A','Z').join();
    

    【讨论】:

      【解决方案3】:
      var chars = [].concat.apply([], Array(26))
                    .map(function(_, i) { return String.fromCharCode(i+65); })
                    .join();
      

      .map 函数可以是可用于不同字符集的函数生成器。

      function charRange(start) {
          var base = start.charCodeAt(0);
          return function(_, i) { return String.fromCharCode(i + base); };
      }
      

      您可能还想创建一个“完整的”数组助手。

      function fullArray(len) { return [].concat.apply([], Array(len)); }
      

      然后像这样使用它们。

      var chars = fullArray(26).map(charRange("A"))
                               .join();
      

      【讨论】:

      • 很好,功能风格比基于循环的答案更易读。这个答案值得更多的支持
      【解决方案4】:

      TL;DR

      // ['a', .. , 'z']
      Array.apply(null, {length: 26})
          .map(function (x,i) { return String.fromCharCode(97 + i) });
      

      甚至

      function range(first, last) {
          var a = first.charCodeAt(0)
          var b = last.charCodeAt(0) + 1
          return Array.apply(null, {length: Math.abs(b - a)})
            .map(function (x,i) { return String.fromCharCode(Math.min(a, b) + i) });
      }
      range('K','M') // => ['K','L','M']
      range('$','z') // => "$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz"
      

      我认为这可以用函数式的方式表达得最清楚:将[0 .. 25] 映射到['a' .. 'z']

      我们可以使用fromCharCode(n) 将数字转换为字符串。要找到一个字符对应的数值,我们需要它的反函数toCharCode(s)

      var toCharCode = function(s){ return s.charCodeAt(0) } // 'a' => 97, 'b' => 98, ..
      

      那么剩下的就简单了:

      Array.apply(null, {length: 26})
           .map(function (x,i) { return String.fromCharCode(97 + i) });
      

      构造一个包含 26 个未定义的数组:[undefined, ... , undefined]。然后map 将每个值的i 索引为97 + i == 'a'.charCodeAt(0) + i(大写从'A' =&gt; 65 开始)。

      第一行可能需要一些解释。我们实际上所做的与Array(1,2,3) == [1,2,3] 相同。我们没有将实际的数组传递给apply,而是传递一些类似数组的东西(具有length 属性)。这导致调用Array(undefined, .. , undefined)

      apply"generic array-like object" 了解更多信息。

      【讨论】:

      • 仅供参考,所有 ASCII 字符的范围是 range(' ','~')——感谢这个功能!
      【解决方案5】:

      查看 kannebec 提供的类似问题的答案。

      Does JavaScript have a method like "range()" to generate an array based on supplied bounds?

      如果您不想添加自己的功能,而是在一行中:

      var abc = 
      (function(){var output = []; for(var i='A'.charCodeAt(0); i <= 'Z'.charCodeAt(0); i++)
          output.push(String.fromCharCode(i)); return output;})().join(',');
      

      【讨论】:

        【解决方案6】:

        CoffeeScript 编译为 javascript,它有数字范围:

        (String.fromCharCode(x+64) for x in [1..26]).join(",")
        

        Here's a link 到 coffeescript.org 站点中的这个脚本。您可以查看它编译成的 javascript,并在您的浏览器中实时运行。

        (还有yes,你可以在Node.js中使用coffeescript)

        【讨论】:

          【解决方案7】:

          略有不同的方法

          String.fromCharCode(..." ".repeat(26).split("").map((e,i)=>i+'A'.charCodeAt()))
          

          打印

          "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
          

          【讨论】:

          • 这是Sring大师的思维方式。很多很酷的答案,反映了对问题的不同思考方式。
          【解决方案8】:

          也许这个功能会对你有所帮助。

          function range ( low, high, step ) {    // Create an array containing a range of elements
              // 
              // +   original by: _argos
          
              var matrix = [];
              var inival, endval, plus;
              var walker = step || 1;
              var chars  = false;
          
              if ( !isNaN ( low ) && !isNaN ( high ) ) {
                  inival = low;
                  endval = high;
              } else if ( isNaN ( low ) && isNaN ( high ) ) {
                  chars = true;
                  inival = low.charCodeAt ( 0 );
                  endval = high.charCodeAt ( 0 );
              } else {
                  inival = ( isNaN ( low ) ? 0 : low );
                  endval = ( isNaN ( high ) ? 0 : high );
              }
          
              plus = ( ( inival > endval ) ? false : true );
              if ( plus ) {
                  while ( inival <= endval ) {
                      matrix.push ( ( ( chars ) ? String.fromCharCode ( inival ) : inival ) );
                      inival += walker;
                  }
              } else {
                  while ( inival >= endval ) {
                      matrix.push ( ( ( chars ) ? String.fromCharCode ( inival ) : inival ) );
                      inival -= walker;
                  }
              }
          
              return matrix;
          }
          
          console.log(range('A','Z')) 
          // ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"]
          

          这不是我的,来自:http://javascript.ru/php/range

          【讨论】:

            【解决方案9】:

            不,JavaScript 没有任何内置的 Range 对象。您需要编写一个函数来创建一个抽象 Range,然后为等价添加一个 to_a 方法。

            为了好玩,这里有另一种获得精确输出的方法,无需中间字符串。

            function commaRange(startChar,endChar){
              var c=','.charCodeAt(0);
              for (var a=[],i=startChar.charCodeAt(0),e=endChar.charCodeAt(0);i<=e;++i){
                a.push(i); a.push(c);
              }
              a.pop();
              return String.fromCharCode.apply(String,a);
            }
            
            console.log(commaRange('A','J')); // "A,B,C,D,E,F,G,H,I,J"
            

            对于 Node.js,有 Lazy 模块。

            【讨论】:

              【解决方案10】:

              https://stackoverflow.com/a/64599169/8784402

              使用单行生成字符列表

              const charList = (a,z,d=1)=>(a=a.charCodeAt(),z=z.charCodeAt(),[...Array(Math.floor((z-a)/d)+1)].map((_,i)=>String.fromCharCode(a+i*d)));
              
              console.log("from A to G", charList('A', 'G'));
              console.log("from A to Z with step/delta of 2", charList('A', 'Z', 2));
              console.log("reverse order from Z to P", charList('Z', 'P', -1));
              console.log("from 0 to 5", charList('0', '5', 1));
              console.log("from 9 to 5", charList('9', '5', -1));
              console.log("from 0 to 8 with step 2", charList('0', '8', 2));
              console.log("from α to ω", charList('α', 'ω'));
              console.log("Hindi characters from क to ह", charList('क', 'ह'));
              console.log("Russian characters from А to Я", charList('А', 'Я'));
              对于打字稿
              const charList = (p: string, q: string, d = 1) => {
                const a = p.charCodeAt(0),
                  z = q.charCodeAt(0);
                return [...Array(Math.floor((z - a) / d) + 1)].map((_, i) =>
                  String.fromCharCode(a + i * d)
                );
              };
              

              【讨论】:

                【解决方案11】:
                function range(r, x) {
                    var c1 = r.charCodeAt(0)+1, c2 = r.charCodeAt(3), s = r[0];
                    if(c1 && c2)while (c1 <= c2) s += (x || "") + String.fromCharCode(c1++);
                    return s;
                }
                
                range("A--S", ",");
                

                【讨论】:

                  【解决方案12】:
                  var range = [];
                  for(var i = 65; i < 91; i++)
                  {
                   range.push(String.fromCharCode(i));
                  }
                  range = range.join(',');
                  

                  给出范围 a-z,但我也喜欢一些函数选项。

                  【讨论】:

                    猜你喜欢
                    • 1970-01-01
                    • 2021-01-10
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 2021-12-01
                    • 1970-01-01
                    • 1970-01-01
                    • 2022-01-24
                    相关资源
                    最近更新 更多