0

I just started learning Javascript and I am trying to implement a project that came into my mind. The project is a simple text editor that takes a text as an input does some corrections and posts an output with the fixed text.

The input text is imported as an array. Each line of the text is an object property. The inputText is for displaying the default text in the browser inside a div, and the outputText is the one I use for the editing.

inputText = loadStrings("v.txt");
outputText = inputText;

Now the input text has some sentences. The problem is that there are a lot of empty lines in between.

firstLine



secondLine






thirdLine

What I want to achieve, is to remove all empty lines, but one, so the output text looks like:

firstLine

secondLine

thirdLine

I am searching for a solution for almost 3 days now. I have managed to remove ALL empty lines, but that's not what i want. I want to remove empty lines if they are more than one, but don't make any change if there is only one empty line.

This piece of code is one of many i have tried. This will remove ALL empty lines:

(source: Remove empty elements from an array in Javascript )

outputText = outputText.filter(function(e){
    return e.replace(/[\r\n]+/g, '\n')});

Here is the codepen with all HTML, CSS and the JS code I am using. https://codepen.io/theokondak/pen/KrNNVz

Mike 'Pomax' Kamermans
  • 49,297
  • 16
  • 112
  • 153
TheoKondak
  • 9
  • 1
  • 5
  • 1
    To clarify, is `inputText` an array, or a string? – Amadan Nov 12 '18 at 12:26
  • The inputText is an object. – TheoKondak Nov 12 '18 at 12:36
  • Without more information as to the structure of said object, it will not be possible to give you an answer. – Amadan Nov 12 '18 at 12:37
  • @Amadan I Have updated the original post with a codepen including all my code. It's on the last line of the original post. – TheoKondak Nov 12 '18 at 12:42
  • It does not help at all, since `loadStrings` is undefined, so there is no indication in code that I can see as to what `inputText` is. `.filter` works only on arrays, not on any other kinds of object, nor on strings. – Amadan Nov 12 '18 at 12:46
  • Please publish whole code, especially function, that prints data from object. – Kamil Naja Nov 12 '18 at 12:48
  • @Amadan that's the whole code. The loadStrings loads from a local text file named v.txt. This file could have any text in the form i've posted at my original post. Unfortunately, i cannot attach my v.txt to codepen. Even though this is an object, the .filter seems to do some work. – TheoKondak Nov 12 '18 at 13:13
  • 1) it can’t be the whole code since `loadStrings` function is not defined (and isn’t part of core JS either). 2) I understand the format of the file; I am asking about the `inputFile` variable. A natural shape for it is either a single string (with newline characters), or array of lines (with or without newlines at end of each); but you insist it is neither of these. 3) categorically, absolutely, `filter` is not available on non-array objects, so if that works, you have an array. Good luck, I don’t think I can help you: it is as if you intentionally make the question vague and contradictory. – Amadan Nov 12 '18 at 13:20
  • what do you mean `input text is imported as an object` ? it's not pasted in? – vsync Nov 12 '18 at 13:33
  • I am sorry @Amadan , I am very new to JavaScript and still not familiar with most of the concepts. It seems that `loadStrings()` is part of `processings.js` library. I didn't have this library included in the HTML file, but somehow it worked. I read a bit about `loadStrings()` and it seems that what it does, is take each line of the text file and put in in an array. The thing now is that when i do `typeof inputText`, it returns that it is an Object and not an array :/ – TheoKondak Nov 12 '18 at 13:34
  • Yeah, no worries, as long as we finally got the information. It would have helped if you included [tag:processing.js] tag. [`typeof`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/typeof) is tricky because it lies. Or rather it doesn't know JavaScript that well either :P But the [`loadStrings` documentation](http://processingjs.org/reference/loadStrings_/) at processing.js says you get an array of individual lines. – Amadan Nov 12 '18 at 16:13

5 Answers5

1

Try this regex:

e.replace(/([\r\n]){2,}/g, '\n\n')});

This will only match two or more consecutive empty lines replacing by an empty line.

My test code:

var lines = 'firstLine\n\n\n\nsecodLine\n\n\n\n\n\n\nthirdLine';
/*
firstLine



secondLine






thirdLine
*/
console.log(lines.replace(/([\r\n]){2,}/g, '\n\n'));

/*
firstLine

secodLine

thirdLine
*/
Purport Tees
  • 464
  • 2
  • 4
  • 12
  • I have tried just your code and it works indeed. In my code though, i have to work with either an object or an array (really i am confused on what it is right now). Maybe your solution would work, if i load the file as one string, and not an object or an array? – TheoKondak Nov 12 '18 at 13:46
  • You can use Array.reduce() to transform your array of lines in a single string containing all the lines before to apply this solution. Something like: arrayOfLines.reduce((final, line) => { return final += line}, ""). – Purport Tees Nov 12 '18 at 14:29
0

Try:

outputText = outputText.filter(function(e){
    return e.replace(/[\r\n]+/g, '\n\n')});

I am not sure about the filter function above. but try below one must work.

outputText = outputText.replace(/[\r\n]+/g, '\n\n');

replacing with two new lines is the simplest way. you will get what you want.

Sindhoor
  • 514
  • 3
  • 14
  • thats what he want. see his question. – Sindhoor Nov 12 '18 at 12:48
  • I have tried this already. whatever i put in the second part of the regular expression field it doesn't make a difference. I have tried replacing \n with \n\n , to leave just some empty quotes or even tried to put some string value to see if it even makes a difference. It does not. – TheoKondak Nov 12 '18 at 12:49
  • it will make difference. i tried and posted the answer. – Sindhoor Nov 12 '18 at 12:50
  • updated answer. use without using filter function. must work. – Sindhoor Nov 12 '18 at 12:55
  • @Sindhoor I've tried the updated single line code you suggested, but i get an error: `index.js:80 Uncaught (in promise) TypeError: outputText.replace is not a function at removeEmptyLines` – TheoKondak Nov 12 '18 at 13:37
  • Hey outputText isn't string? then replace function would not work. – Sindhoor Dec 24 '18 at 12:53
0

I don't know if loadStrings leaves newlines at the end of the line or not. I'll assume it does (based on some code I see on this page). If it ends up mangled, please say so.

It is definitely easier to do this on a single string, like Hélio Márcio Filho says. So in your case, where you start with an array, you could just join the array together,replace three or more newlines with just two, then split it back up into lines:

let outputText = inputText.join('').replace(/(?:\r?\n){3,}/g, '\n\n').
  split(/\n/).map(line => line + "\n");

But you can also do it just with filter - you just need to know how many empty lines you just saw, and suppress the extra ones:

let empties = 0;
let outputText = inputText.filter(line => {
  if (line.replace(/[\r\n]+/, '')) empties = 0;
  else empties++;
  return empties <= 1;
});
Amadan
  • 191,408
  • 23
  • 240
  • 301
0

The other answers work with a single string, but you're using the loadStrings() function from Processing.js, which gives you an array of strings.

You could convert the array into a single string, or load the file as a single string, but it seems simplest to me if you just process the array. Something like this:

function reduceNewlines(inputArray){

  var outputNewArray = [];
  var previousLineWasNewline = false;

  for(var i = 0; i < myArray.length; i++){
    if(myArray[i] == ''){
      if(!previousLineWasNewline){
        outputArray.push('');
      }
      previousLineWasNewline = true;
    }
    else{
      outputArray.push(myArray[i]);
      previousLineWasNewline = true;
    }
  }
  return outputArray;
}

Please note that I haven't tested this code, and there is probably a ton of room for improvement. But the general idea is there: you could write a function that processed the array and returned a new array with the consecutive newlines removed.

You might also consider pre-processing your text file so you don't have to do this at all.

Kevin Workman
  • 41,537
  • 9
  • 68
  • 107
0

First of all, I would like to thank everyone for trying to help. I studied all your replies, I've tested each of them and they all work (some with needed tweaking) as stand-alone code, but when I inserted them into my code, some things went wrong. So I struggled and came out with my own solution, which is greatly inspired by your comments.

So the code that worked in my case is :

function reduceNewlines(outputTextEditNewLines) {

  for (let key = 0; key < outputTextEditNewLines.length; key++) {
    if (outputTextEditNewLines[key] == '') outputTextEditNewLines[key] = '\n';
    else outputTextEditNewLines[key] = outputTextEditNewLines[key];
  }

  arrayToString = outputTextEditNewLines.join(""); // convert object myArray to string
  console.log(arrayToString.replace(/([\r\n]){1,}/g, '\n\n')); // exports the text as it should

  return arrayToString.replace(/([\r\n]){1,}/g, '\n\n');

}

The console.log exports the text as it should. Now the next step for my project is to make this string print to the DOM as it prints in the console.log.

TheoKondak
  • 9
  • 1
  • 5