├── .gitignore ├── .travis.yml ├── LICENSE ├── README.md ├── index.d.ts ├── index.js ├── package.json └── test └── test.js /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | 5 | # Runtime data 6 | pids 7 | *.pid 8 | *.seed 9 | 10 | # Directory for instrumented libs generated by jscoverage/JSCover 11 | lib-cov 12 | 13 | # Coverage directory used by tools like istanbul 14 | coverage 15 | 16 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 17 | .grunt 18 | 19 | # Compiled binary addons (http://nodejs.org/api/addons.html) 20 | build/Release 21 | 22 | # Dependency directory 23 | # Deployed apps should consider commenting this line out: 24 | # see https://npmjs.org/doc/faq.html#Should-I-check-my-node_modules-folder-into-git 25 | node_modules 26 | package-lock.json -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - 9 4 | - node 5 | branches: 6 | only: 7 | - master 8 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2014, Euank 2 | 3 | Permission to use, copy, modify, and/or distribute this software for any 4 | purpose with or without fee is hereby granted, provided that the above 5 | copyright notice and this permission notice appear in all copies. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8 | WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9 | MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 10 | ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11 | WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 12 | ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 13 | OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 14 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | node-parse-numeric-range 2 | ======================== 3 | 4 | Parses expressions like 1-10,20-30. Returns an energetic (as opposed to lazy) array. 5 | 6 | 7 | ## Supported Expressions 8 | Comprehensive supported expression examples: 9 | 10 | | Expression | result | 11 | |:----------:|:------------:| 12 | | | [] | 13 | | 1 | [1] | 14 | | 1,2 | [1,2] | 15 | | -10 | [-10] | 16 | | -3,-3 |[-3, -3] | 17 | | -1-2,-2 |[-1,0,1,2,-2] | 18 | | -1--2 |[-1,-2] | 19 | | -1..2,-2 |[-1,0,1,2,-2] | 20 | | -1...3,-2 |[-1,0,1,2,-2] | 21 | | 1⋯3 |[1,2] | 22 | | 1…3 |[1,2] | 23 | | 1‥3 |[1,2,3] | 24 | 25 | 26 | What's this useful for? Well, letting users input these sorts of things and then 27 | making them programmatically useful. 28 | 29 | 30 | ## Usage 31 | 32 | First, `npm install parse-numeric-range`. 33 | 34 | ```javascript 35 | const rangeParser = require("parse-numeric-range"); 36 | 37 | const numbers = rangeParser("4,6,8-10,12,14..16,18,20...23"); 38 | 39 | console.log( 40 | `The first ${numbers.length} composite numbers are: ${numbers.join(", ")}`, 41 | ); 42 | ``` 43 | 44 | ### ES6 45 | ```jsx 46 | import rangeParser from "parse-numeric-range"; 47 | 48 | const numbers = rangeParser("4,6,8-10,12,14..16,18,20...23"); 49 | 50 | console.log( 51 | `The first ${numbers.length} composite numbers are: ${numbers.join(", ")}`, 52 | ); 53 | ``` -------------------------------------------------------------------------------- /index.d.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Parses expressions like `1-10,20-30`. Returns an energetic (as opposed to lazy) array. 3 | * @param expression a numeric range expression 4 | */ 5 | declare function parse(expression: string): number[]; 6 | export = parse; -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @param {string} string The string to parse 3 | * @returns {Array} Returns an energetic array. 4 | */ 5 | function parsePart(string) { 6 | let res = []; 7 | let m; 8 | 9 | for (let str of string.split(",").map((str) => str.trim())) { 10 | // just a number 11 | if (/^-?\d+$/.test(str)) { 12 | res.push(parseInt(str, 10)); 13 | } else if ( 14 | (m = str.match(/^(-?\d+)(-|\.\.\.?|\u2025|\u2026|\u22EF)(-?\d+)$/)) 15 | ) { 16 | // 1-5 or 1..5 (equivalent) or 1...5 (doesn't include 5) 17 | let [_, lhs, sep, rhs] = m; 18 | 19 | if (lhs && rhs) { 20 | lhs = parseInt(lhs); 21 | rhs = parseInt(rhs); 22 | const incr = lhs < rhs ? 1 : -1; 23 | 24 | // Make it inclusive by moving the right 'stop-point' away by one. 25 | if (sep === "-" || sep === ".." || sep === "\u2025") rhs += incr; 26 | 27 | for (let i = lhs; i !== rhs; i += incr) res.push(i); 28 | } 29 | } 30 | } 31 | 32 | return res; 33 | } 34 | 35 | exports.default = parsePart; 36 | module.exports = parsePart; 37 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "parse-numeric-range", 3 | "version": "1.3.0", 4 | "description": "Takes a string, such as \"1,2,3-10,5-8\" and turns it into an array of numbers", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "./node_modules/mocha/bin/mocha --require esm" 8 | }, 9 | "keywords": [ 10 | "parse", 11 | "numbers", 12 | "ranges", 13 | "utility", 14 | "arrays" 15 | ], 16 | "author": "Euan Kemp", 17 | "license": "ISC", 18 | "homepage": "https://github.com/euank/node-parse-numeric-range", 19 | "repository": { 20 | "type": "git", 21 | "url": "https://github.com/euank/node-parse-numeric-range.git" 22 | }, 23 | "devDependencies": { 24 | "chai": "*", 25 | "mocha": "*", 26 | "esm": "*" 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /test/test.js: -------------------------------------------------------------------------------- 1 | import { expect } from 'chai' 2 | import strparse from '../index.js' 3 | 4 | function peq(x, y) { 5 | expect(strparse(x)).to.eql(y); 6 | } 7 | 8 | describe('range-parser', function(){ 9 | describe('#parse', function(){ 10 | it('should parse 1', function() { 11 | peq('1', [1]); 12 | }); 13 | it('should parse 1,1', function(){ 14 | peq('1,1', [1,1]); 15 | }); 16 | it('should parse 1-5', function(){ 17 | peq('1-5', [1,2,3,4,5]); 18 | }); 19 | it('should parse 5-1', function(){ 20 | peq('5-1', [5,4,3,2,1]); 21 | }); 22 | it('should parse 1-3,5-6', function(){ 23 | peq('1-3,5-6', [1,2,3,5,6]); 24 | }); 25 | it('should parse 10..15', function(){ 26 | peq('10..15', [10,11,12,13,14,15]); 27 | }); 28 | it('should parse 10...15', function(){ 29 | peq('10...15', [10,11,12,13,14]); 30 | }); 31 | it('should parse 10..12,13...15,2,8', function(){ 32 | peq('10..12,13...15,2,8', [10,11,12,13,14,2,8]); 33 | }); 34 | it('should parse ""', function(){ 35 | peq('', []); 36 | }); 37 | it('should parse -5', function(){ 38 | peq('-5', [-5]); 39 | }); 40 | it('should parse -5--10', function(){ 41 | peq('-5--10', [-5,-6,-7,-8,-9,-10]); 42 | }); 43 | it('should parse -1..2,-1...2', function(){ 44 | peq('-1..2,-1...2', [-1,0,1,2,-1,0,1]); 45 | }); 46 | it('should parse 1‥3', function() { 47 | peq('1‥3', [1,2,3]); 48 | }); 49 | it('should parse 1⋯3', function() { 50 | peq('1⋯3', [1,2]); 51 | }); 52 | it('should parse 1…3', function() { 53 | peq('1…3', [1,2]); 54 | }); 55 | it('should parse ranges with a space in between', function() { 56 | peq('1-2, 3-4', [1,2,3,4]); 57 | }); 58 | }); 59 | }); 60 | --------------------------------------------------------------------------------