首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何将字符串中的所有罗马数字替换为阿拉伯文等价物?

如何将字符串中的所有罗马数字替换为阿拉伯文等价物?
EN

Stack Overflow用户
提问于 2016-11-21 15:29:49
回答 3查看 803关注 0票数 7

我有一个所有莎士比亚十四行诗的列表,我正在做一个函数来搜索每一个十四行诗。但是,我希望能够使用阿拉伯数字(例如"/sonnet 122“)搜索它们。.txt的格式是这样的:

代码语言:javascript
复制
I

This is a sonnet

II

This is a second sonnet

我现在正在使用节点来尝试,但从昨天开始我一直在尝试,但没有结果。我昨天的最后一次尝试是这样使用“替换”方法:

代码语言:javascript
复制
'use strict';
//require module roman-numerals, which converts roman to arabic
var toArabic = require('roman-numerals').toArabic;
//require file-handling module
var fs = require('fs');

fs.readFile('sonn.txt', 'utf8', function (err,data) {
    if (err) {
        console.log(err);
    } else {
        var RN = /[A-Z]{2,}/g; 
        var found = data.match(RN); //finds all roman numbers and puts them in an array
        var numArr = [];
        for (var i = 0; i < found.length; i++ ){
            numArr.push(toArabic(found[i])); //puts all arabic numbers in numArr
        }
        for (var e = 0; e < found.length; e++){
            data.replace(found, found.forEach((x, i)=> {
            toArabic(x)
    }
});

然后我试着用:

代码语言:javascript
复制
data.replace(found, function(s, i){
    return numArr[i];
});

然后我尝试了一个for循环。我没有保留这段代码,但就像:

代码语言:javascript
复制
for(var i=0;i<found.length;i++){
    data.replace(found, numArr[i]);
}

最后一个代码替换每个数字,然后删除数据,然后将下一个数字替换为这样:

代码语言:javascript
复制
replace(abc, 123) -> 1bc, a2c, ab3

如何使它迭代数据中的每个事件并保存它?那么将它保存到一个新的txt应该很容易。

(而且,我的RegExp只查找多个字符的罗马数字,以避免替换行尾可以找到的孤独I。)

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2016-11-21 16:14:08

您必须将替换的字符串写回,并且可以为replace()使用回调。

代码语言:javascript
复制
'use strict';

var toArabic = require('roman-numerals').toArabic;
var fs = require('fs');

fs.readFile('sonn.txt', 'utf8', function (err,data) {
    if (err) {
        console.log(err);
    } else {
        data = data.replace(/[A-Z]{2,}/g, function(x) {
            return toArabic(x);
        });
    }
});

下面是一些与罗马人匹配的正则表达式

票数 1
EN

Stack Overflow用户

发布于 2016-11-21 15:58:19

如果使用String.prototype.replace,则可以使用正则表达式和自定义替换函数。您只需要返回要用作替换的值,这就是toArabic所做的。

代码语言:javascript
复制
var data = 'I\n\nThis is a sonnet\n\nII\n\nThis is a second sonnet';

//========================

var toArabic = (function () {
  var forEach = Array.prototype.forEach;


  /**
   * Converts a roman number to its arabic equivalent.
   *
   * Will throw TypeError on non-string inputs.
   *
   * @param {String} roman
   * @return {Number}
   */
  function toArabic (roman) {
    if (('string' !== typeof roman) && (!(roman instanceof String))) throw new TypeError('toArabic expects a string');

    // Zero is/was a special case. I'll go with Dionysius Exiguus on this one as
    // seen on http://en.wikipedia.org/wiki/Roman_numerals#Zero
    if (/^nulla$/i.test(roman) || !roman.length) return 0;

    // Ultra magical regexp to validate roman numbers!
    roman = roman.toUpperCase().match(/^(M{0,3})(CM|DC{0,3}|CD|C{0,3})(XC|LX{0,3}|XL|X{0,3})(IX|VI{0,3}|IV|I{0,3})$/);
    if (!roman) throw new Error('toArabic expects a valid roman number');
    var arabic = 0;

    // Crunching the thousands...
    arabic += roman[1].length * 1000;

    // Crunching the hundreds...
    if (roman[2] === 'CM') arabic += 900;
    else if (roman[2] === 'CD') arabic += 400;
    else arabic += roman[2].length * 100 + (roman[2][0] === 'D' ? 400 : 0);


    // Crunching the tenths
    if (roman[3] === 'XC') arabic += 90;
    else if (roman[3] === 'XL') arabic += 40;
    else arabic += roman[3].length * 10 + (roman[3][0] === 'L' ? 40 : 0);

    // Crunching the...you see where I'm going, right?
    if (roman[4] === 'IX') arabic += 9;
    else if (roman[4] === 'IV') arabic += 4;
    else arabic += roman[4].length * 1 + (roman[4][0] === 'V' ? 4 : 0);
    return arabic;
  };
  return toArabic;
})();

//====================

var RN = /[A-Z]{1,2}(?=\n)/g;
var newData = data.replace(RN, toArabic);
document.body.innerText = newData;

票数 1
EN

Stack Overflow用户

发布于 2016-11-21 16:31:16

这种事情最好作为一个流变换来处理。旧的节点流转换库对于初始化来说有点古怪,但是它能很快地很好地完成工作。下面是一个使用@adeneo上面写的替换函数的工作示例。

代码语言:javascript
复制
var stream = require('stream');
var util = require('util');
var toArabic = require('roman-numerals').toArabic;
var fs =require('fs');

var rstream = fs.createReadStream('sonnets.txt');
var wstream = fs.createWriteStream('sonnets.transformed.txt');

// node v0.10+ use native Transform, else polyfill
var Transform = stream.Transform ||
  require('readable-stream').Transform;

function Converter(options) {
    // allow use without new
    if (!(this instanceof Converter)) {
        return new Converter(options);
    }

    // init Transform
    Transform.call(this, options);
}

util.inherits(Converter, Transform);

Converter.prototype._transform = function (chunk, enc, cb) {

    //transform the chunk
    var data = chunk.toString().replace(/[A-Z]{2,}/g, function(x) {
            return toArabic(x);
        });

    this.push(data); //push the chunk

    cb(); //callback

};


// try it out
var converter = new Converter();

// now run it on the whole file
rstream
    .pipe(converter)
    .pipe(wstream)  // writes to sonnets.transformed.txt
    .on('finish', function () {  // finished
        console.log('done transforming');
     });

这里很好地介绍了这一点:http://codewinds.com/blog/2013-08-20-nodejs-transform-streams.html,以及使用through2 transform libs https://github.com/substack/stream-handbook的更现代示例

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/40723730

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档