2016-11-21 3 views
7

Ich habe eine Liste aller Shakespeare Sonette und ich mache eine Funktion für jedes Sonett zu suchen. . Aber ich mag, dass sie arabische Zahlen verwendet suchen kann (zum Beispiel „/ Sonett 122“ Die .txt wird auf diese Weise formatiert:Wie ersetzt man alle römischen Zahlen in einer Zeichenkette für das arabische Äquivalent?

I 

This is a sonnet 

II 

This is a second sonnet 

I-Knoten im Augenblick verwenden, um zu versuchen, es zu tun, aber ich habe ohne Erfolg seit gestern versucht, meine letzten versuchen gestern wurden mit der ‚ersetzen‘ Methode als solche.

'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) 
    } 
}); 

Dann habe ich versucht, sie mit dem ersetzen:

data.replace(found, function(s, i){ 
    return numArr[i]; 
}); 

Dann habe ich versucht, mit eine for-Schleife, die ich nicht behalten habe dass Code, aber es war so etwas wie:

for(var i=0;i<found.length;i++){ 
    data.replace(found, numArr[i]); 
} 

Der letzte Code jede Nummer ersetzt und löscht dann die Daten und ersetzt die nächste Nummer als solche:

replace(abc, 123) -> 1bc, a2c, ab3 

Wie mache ich es jedes Auftreten iterieren in den Daten und behalte es? Dann sollte es einfach in einem neuen txt gespeichert werden.

(Auch mein RegExp findet nur mehrere Zeichen römische Zahlen ersetzt einsames Ich zu vermeiden, die am Ende einer Zeile nicht gefunden werden.)

+0

Also Sie versuchen, römische Ziffern regelmäßig Ziffern zu konvertieren? Wie wäre es mit -> http://blog.stevenlevithan.com/archives/javascript-roman-numeral-converter – adeneo

+0

Hier ist eine Reihe von Beispielen in Java -> http://stackoverflow.com/questions/9073150/converting-roman-numerals -to-decimal – adeneo

+0

@adeneo das Modul "römische Ziffern" konvertiert sie, aber es nimmt nur Strings als Wert, also muss ich es innerhalb der Replace-Funktion oder innerhalb der Schleife verwenden, so dass jede Iteration gibt es eine Zeichenfolge. Mein Problem ist nicht das Konvertieren, sondern das Ersetzen aller Vorkommnisse in der ursprünglichen Zeichenfolge, die die TXT-Datei ist. – Besto

Antwort

1

Sie haben die ersetzt String zurück zu schreiben, und man konnte einen Rückruf für replace()

'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); 
     }); 
    } 
}); 

Here are some more regular expressions to match romans

+0

Alter, das war es, bist du ein Zauberer? Hahaha. – Besto

+0

Ich denke, der Hauptunterschied war, dass Sie "Daten" neu deklariert haben. – Besto

+0

@Besto - Gern geschehen. Strings sind unveränderlich, also müssen Sie sie immer "zurückschreiben", auch dies verwendet nur den globalen Regex direkt im Ersetzen, und dann gibt der Callback den Wert aus der 'toArabic'-Funktion zurück. Alles in Arrays zu setzen ist viel komplizierter, um richtig zu machen. – adeneo

1

Wenn Sie String.prototype.replace verwenden, können Sie Ihren regulären Ausdruck und ein benutzerdefinierte verwenden können Ersatzfunktion. Sie müssen nur den Wert als Ersatz zurückgeben, was toArabic tut.

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;

+0

Bekam Dinge wie CXLV2 CXL6 CX55 XCVI2 (III wurde zu I2 konvertiert). Ansonsten lese ich deinen Code und es ist großartig. – Besto

+0

Richtig, ich habe nicht versucht, welche Regex-Syntax Sie verwenden sollten. Ich zeige Ihnen nur, wie der Ersatz funktioniert. –

+0

Aaaah, in Ordnung. Entschuldige, dass du dich falsch verstanden hast. Am Ende habe ich es genau so gemacht, wie Sie es vorgeschlagen haben, aber nach adeneo's Antwort. Ich denke, wenn ich deine Absicht verstanden hätte, wäre es früher richtig gegangen. : P – Besto

1

Diese Art der Sache verwenden am besten behandelt, als a stream transform. Die alte Node-Stream-Transformationsbibliothek ist ein bisschen unkonventionell zu initialisieren, aber sie erledigt den Job sehr schnell und gut. Hier ist ein Arbeitsbeispiel, das die Ersetzungsfunktion verwendet, die @adeneo oben geschrieben hat.

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'); 
    }); 

Dieser ziemlich gut hier behandelt: http://codewinds.com/blog/2013-08-20-nodejs-transform-streams.html und hier mit moderneren Beispielen der Libs through2-Transformation https://github.com/substack/stream-handbook

+0

Das funktioniert auch :) Was würden Sie sagen, sind die Profis und Nachteile der Verwendung dieser anstelle von Adeneos einfachen Ersatzmethode? – Besto

+0

Ich meine, die Antwort von Adeneo wird nicht geändert. Was sind die Vor- und Nachteile dieses Moduls anstelle des Moduls "fs"? – Besto

+0

Kein Problem, wenn Sie mit einer Datei arbeiten, aber abhängig von der Dateigröße gibt es Speicherbeschränkungen, wenn Sie keine Streams verwenden, da Sie die gesamte Datei puffern müssen, bevor Sie an den Zeilen arbeiten. https://github.com/substack/stream-handbook#why-you-should-use-streams – 4m1r

Verwandte Themen