JavaScript to split string by end of line character and read each line
Asked Answered
R

6

7

I have a need to loop through a large string with several eol characters and read each of these lines looking for characters. I could've done the following but I feel that its not very efficient as there could be more than 5000 characters in this large string.

var str = largeString.split("\n");

and then loop through str as an array

I cant really use jquery and can only use simple JavaScript.

Is there any other efficient way of doing this?

Rollback answered 4/11, 2013 at 3:12 Comment(4)
hmmm...you can use web workers, you can parse string in the background. w3schools.com/html/html5_webworkers.aspTensor
what about using a regular expression?Placia
This should work just fine - there is no obvious way to do it simpler. 5000 characters is nothing for a modern computer, even a smartphone. Do you have some evidence that this is too slow?Alexandriaalexandrian
5000 is just a minimum number I'm expecting. but it could well be 100000 characters. i realize theres no other efficient way of achieving this. for e.g. in java theres StringReader for this purpose.Rollback
C
6

You could always use indexOf and substring to take each line of the string.

var input = 'Your large string with multiple new lines...';
var char = '\n';
var i = j = 0;

while ((j = input.indexOf(char, i)) !== -1) {
  console.log(input.substring(i, j));
  i = j + 1;
}

console.log(input.substring(i));

Edit I didn't see this question was so old before answering. #fail

Edit 2 Fixed code to output final line of text after last newline character - thanks @Blaskovicz

Carolecarolee answered 6/3, 2017 at 5:4 Comment(2)
As someone who's having the same question in 2017, I'm glad you posted this answer in spite of the old question, it's the best one so farNichols
Also, for the people reading this, remember that this won't get the trailing characters like input.split(char) would if their is no ending delimitter. If you need to do that, you can just check if input.length === i (meaning there were no trailing characters).Cheekbone
B
2

5000 doesn't seem that intense for a modern JavaScript engine. Of course it depends on what you do on each iteration too. For clarity I recommend using eol.split and [].forEach.

eol is an npm package. In Node.js and CommonJS you can npm install eol and require it. In ES6 bundlers you can import. Otherwise loaded via <script> eol is global

// Require if using Node.js or CommonJS
const eol = require("eol")

// Split text into lines and iterate over each line like this
let lines = eol.split(text)
lines.forEach(function(line) {
  // ...
})
Bypath answered 26/6, 2017 at 0:13 Comment(3)
First line produce exception: Uncaught ReferenceError: require is not definedApprehensive
Also split works exactly opposite ot the example. The correct version is: string.split(symbolForSplitting)Apprehensive
@LeonidMednikov Answer clarified. require is for Node.js or CommonJS. Otherwise skip that line. eol.split is a library method different from "".split. Next time please consider asking questions before downvoting without understanding : )Bypath
S
2

If you are using NodeJS, and have a large string to process line-by-line:

const Readable = require('stream').Readable
const readline = require('readline')

promiseToProcess(aLongStringWithNewlines) {
    //Create a stream from the input string
    let aStream = new Readable();
    aStream.push(aLongStringWithNewlines);
    aStream.push(null);  //This tells the reader of the stream, you have reached the end

    //Now read from the stream, line by line
    let readlineStream = readline.createInterface({
      input: aStream,
      crlfDelay: Infinity
    });

    readlineStream.on('line', (input) => {
      //Each line will be called-back here, do what you want with it...
      //Like parse it, grep it, store it in a DB, etc
    });

    let promise = new Promise((resolve, reject) => {
      readlineStream.on('close', () => {
        //When all lines of the string/stream are processed, this will be called
        resolve("All lines processed");
      });
    });

    //Give the caller a chance to process the results when they are ready
    return promise;
  }
Supersonics answered 9/8, 2019 at 15:37 Comment(0)
K
0

You could read it character by character manually and call a handler when you get a newline. It is unlikely to be more efficient in terms of CPU usage but will likely take up less memory. However, as long as the string is less than a few MBs, it should not matter.

Koester answered 28/11, 2016 at 12:18 Comment(0)
H
0
function findChar(str, char) {
    for (let i = 0; i < str.length; i++) {
        if (str.charAt(i) == char) {
            return i
        }
    }
    return -1
}
Halation answered 1/6, 2021 at 3:11 Comment(0)
T
-1

So, you know how to do it, you're just making sure there's no better way to do it? Well, I'd have to say the way you've mentioned is exactly it. Although you may want to look up a regex match if you're looking for certain text split by certain characters. A JS Regex Reference can be found Here

This would be useful if you know how the text is going to be setup, something akin to

var large_str = "[important text here] somethign something something something [more important text]"
var matches = large_str.match(\[([a-zA-Z\s]+)\])
for(var i = 0;i<matches.length;i++){
   var match = matches[i];
   //Do something with the text
}

Otherwise, yes, the large_str.split('\n') method with a loop is probably best.

Teachin answered 4/11, 2013 at 3:26 Comment(2)
A regex is very unlikely to be faster than .split(). Also, I don't think this will work because \s includes \n do it won't break on line boundaries.Alexandriaalexandrian
Considering I don't know how he's going to be looking for it, I gave him what I could. If I knew more, I could help more. I suppose he could .split() something and then use a regex per string to find whatever it was he wanted.Teachin

© 2022 - 2024 — McMap. All rights reserved.