How to insert new line after N char count in javascript? - javascript

I have a string which may have new line '\n' char in it. Now I want to insert new line '\n' after every 4 (or N) chars in that string.
For example:
1)
INPUT: "I am John Doe."
OUTPUT: "I am\nJohn\nDoe"
In above example inserting '\n' after 4 char including space
2)
INPUT: "I\nam John Doe"
OUTPUT: "I\nam J\nohn \nDoe"
In above example inserting space after 4 chars after first '\n' already present in the string
3)
INPUT: 12345\n67890
OUTPUT: 1234\n5\n6789\n0
4)
INPUT: "1234\n56\n78901"
OUTPUT: "1234\n56\n7890\n1"
So far I have created a function which inserts '\n' after every 4 chars but it does not consider '\n' if it is already present in the original string.
function addNewlines(str) {
if (str.length >= 4) {
var result = '';
while (str.length > 0) {
result += str.substring(0, 4) + '\n';
str = str.substring(4);
}
return result;
}
return str;
}
I call this function on every keypress and pass the original string and get output and use it further. I hope you understand what I meant to say here. It should preserve the previously inserted new lines.
Let me know I can explain further. With more examples.

Here is my best guess as to what is being asked for :
function addNewLines (str) {
return str.replace (/(?!$|\n)([^\n]{4}(?!\n))/g, '$1\n');
}
Some test strings and their results :
"I am John Doe.", -> "I am\n Joh\nn Do\ne."
"I\nam John Doe", -> "I\nam J\nohn \nDoe"
"12345\n67890", -> "1234\n5\n6789\n0"
"1234\n56\n78901", -> "1234\n56\n7890\n1"
"ABCD\nEFGH\nIJKL", -> "ABCD\nEFGH\nIJKL\n"
"1234", -> "1234\n"
"12341234" -> "1234\n1234\n"
For those of you for whom regular expressions are mysterious here is a breakdown:
---------------------------- (?! Check that following character(s) are not
| ------------------------- $|\n Beginning of string or a newline character
| | --------------------- )
| | | -------------------- ( Start of capture group 1
| | || ------------------ [^\n] Any single character other than newline
| | || | -------------- {4} Previous element repeated exactly 4 times
| | || | | ----------- (?! Check that following character(s) are not
| | || | | | --------- \n a newline
| | || | | | | ------- )
| | || | | | | |------ ) End of capture group 1
| | || | | | | || ---- /g in replace causes all matches to be processed
| | || | | | | || |
/(?!$|\n)([^\n]{4}(?!\n))/g

function parseInput(str, char, length){
var split = str.split(char),
regex = RegExp('(.{' + length + '})','g');
split[split.length-1] = split[split.length - 1].replace(regex, '$1' + char);
return split.join(char);
}
console.log(parseInput("I am John Doe.", "\n", 4));
// output = "I am\n Joh\nn Do\ne."

Split the string by "\n" str.split("\n"). You get an array of strings.
Do your additional parsing and manipulation checking the element length and putting the result in a new array results.
Join the strings using results.join("\n").
This will remove "\n" duplicates too if you avoid to append or prepend "\n" to results elements.

Here is my code:
function ngram_insert (n, ins, input)
{
var output = "";
var i = 0;
while (i < strlen(input))
{
if (i > 0 && i % n == 0)
{
output += ins;
}
output += input[i];
i++;
}
return output;
}
Test:
var output = ngram_insert (3, "\n", "This is a test.");

function f(n, ins, str) {
if (str.length == 0)
return "";
var i = str.indexOf("\n"), len = str.length, newStr;
if (i == -1) {
i = 1;
newStr = str[0];
}
else {
newStr = str.substring(0, i + 1);
}
var k = 1;
while (k + i < len) {
newStr += str[k + i];
if (k % n == 0) {
newStr += ins;
}
k++;
}
return newStr;
}
Calling f(4, "\n", "I\nam John Doe"); returns "I\nam J\nohn \nDoe"

Related

Converting prefix to infix in JavaScript

I am trying to write a program that takes in an prefix expression and outputs an infix expression. I have examples listed below to help demonstrate what I am talking about. I have pasted my code below, could someone please help me figure out how I can move the symbol between 2 numbers in an expression? Please see example 1 to see my approach on how I tried to get it, but it doesn't work. Any answers would be helpful or tips as to what to do. Thank you for your help!
/* The goal is to take in an expression in prefix notation and output it in infix notation
for example:
+ 1 2 outputs output 1 + 2
+ - 3 4 5 outputs 3 + 4 - 5
% + / - 0 9 3 8 5 outputs 0 % 9 + 3 / 8 - 5
*/
function convert(input){
var x = input.split(''); // splits each variable and stores it in an array
var output = "";
// these are the valid symbols we can take, we will use these later
var symbols = ['+', '-', '*', '/', '%'];
// lets loop through all the values in x, starting at position 0
for(var i = 0; i < x.length; i++){
if(symbols.includes(x[i])) { // we hit a symbol, lets move it between 2 numbers
/* now we need to figure out where to store the symbol. every 2 spaces starting at index 0
we can insert a symbol (so spots like 1 3 5 7 etc). this loop will help us figure out what spot is empty
, and it will store the symbol at that spot [see example 1 for a visualizaton]*/
for(var j = 0; j < input.length; j+=2){
if(output[j] == " "){
// great, we can save the symbol here
output = output + x[i];
}
}
}
// otherwise we have a number on our hands
else{
output = output + x[i];
console.log(output);
}
}
}
console.log(convert("+ 1 2"));
/*
example 1
if I have "+ 1 2"
+ is position 0
1 is position 2
2 is position 4
so the whitespace is at position 1 and 3. these are the spots where we can output the symbols
using the original expression + 1 2
position: value:
-------- | ------
0 | 1
-------- | ------
1 | " "
-------- | ------
2 | +
-------- | ------
3 | " "
-------- | ------
4 | 2
*/
function result_expression(expression, variables) {
let opernads=['+','-','*','/'];
let arr=[...expression.split(" ")];
var len=arr.length;
while(len>0){
let d1=arr[len-1]
let d2=arr[len-2]
let d3=arr[len-3]
if(opernads.includes(d3)){
if(isNaN(d2)){
let tmp=variables[d2]
d2=tmp;
}
if(isNaN(d1)){
let tmp1=variables[d1]
d1=tmp1;
}
let a=d2.toString().concat(d3).concat(d1)
delete arr[len-1]
delete arr[len-2]
delete arr[len-3]
let na=[];
arr[len-3]=eval(a)
arr.forEach(e=>{
if(!(typeof e==='undefined')){
na.push(e)
}
})
arr=[...na]
console.log('arr',arr)
len=arr.length;
// arr=[...newar]
// len=arr.length
}else{
len--
}
if(len==1){
return arr[0]
}
}
}
//let expression="+ 6 * - 4 + 2 3 8";
//let expression="+ 6 * - 4 a b + 2 3 8";
let expression="+ * 6 5 3 2 2";
let variables={a:20,b:1}
let k=result_expression(expression, variables);
console.log('finalresult',k)
So long as you're only using simple expressions, I would suggest dividing the input into two arrays, numbers and symbols, and then merging them together.
var symbols = ['+', '-', '*', '/', '%'];
function convert(input) {
var
response = '',
infixes = [],
numbers = [];
// Divide input into two arrays, infixes (or symbols) and numbers
infixes = input.split(' ').filter(function(o) {
if (symbols.includes(o)) {
return true;
} else {
numbers.push(o);
}
});
// Merge arrays
for (let i = 0; i < numbers.length; i++) {
if (infixes[i]) {
response =
response +
numbers[i] + ' ' +
infixes[i] + ' ';
} else {
response =
response + numbers[i] + ' ';
}
}
response = response.slice(0, -1);
return response;
};
This function works for all your examples, but if you need to make it more intelligent you can easily modify and test the above function on codepen here.

How to get the keyword from this kind of String

I need to get the "payment type and the customer type from this kind of string
Examples:
| D | A | B | C |
| NZ | AAA | BBB | NZ |
| AZ | CCC | DDD | AZ |
| CA | EEE | FFF | CA |
should I try the get the pattern and write a function for this? or I can find some library to detect it
so the output should be
{payment:["AAA","CCC",'EEE'],
customer:["BBB",'DDD","FFF"]}
function detect(str){
let countBar=1
let countBar2=0
let paymentLoc=NaN
let customerLoc=NaN
let after =0
let arr1=str.split(" ")
arr1=arr1.filter(item=>{return item!==""})
let newStr=''
for(let i=0;i<arr1.length;i++){
arr1[i].trim()
if(arr1[i]==='|'){
countBar++
}
if(arr1[i]==="||"){
countBar2++
}
if(arr1[i].includes("payment")){
paymentLoc=i
}
after=((countBar/(countBar2))-1)*2
let sol=[]
for(let i=0;i<arr1.length;i++){
if(arr1[i].includes("payment")){
console.log('payment index',i)
sol.push(arr1[i+after+1])
}
if(arr1[i].includes("customer")){
console.log('customer index',i)
sol.push(arr1[i+after+1])
}
}
newStr=arr1.join('')
console.log(newStr)
}
I had some fun with this one. My first thought was to use an npm package, since the string looks a lot like CSV with | as the delimiter. The package csvtojson is a good one, but why use a well-regarded library when you can hack something together?
Here's my first attempt (in Typescript):
const exampleString = ` | market | payment type | customer type | translation |
| NZ | AAA | BBB | NZ |
| AZ | CCC | DDD | AZ |
| CA | EEE | FFF | CA |`;
const cleanColumn = (col: string) =>
col
.replace("|", "")
.trim()
.replace(/\s/, "_");
const cleanRow = (row: string) =>
row
.split(/\s\|/)
.map(cleanColumn)
.filter(Boolean);
const pivotRows = (
pivoted: string[][],
currentRow: string[],
rowIndex: number
) => {
if (rowIndex === 0) {
currentRow.forEach((col, colIndex) => {
pivoted[colIndex] = [col];
});
} else {
currentRow.forEach((col, colIndex) => {
pivoted[colIndex].push(col);
});
}
return pivoted;
};
const buildObject = (
obj: { [key: string]: string[] },
currentRow: string[]
) => {
let currentCol: string;
currentRow.forEach((col, index) => {
if (index === 0) {
currentCol = col;
obj[currentCol] = [];
} else {
obj[currentCol].push(col);
}
});
return obj;
};
const detect = (str: string) =>
str
.split("\n")
.map(cleanRow)
.reduce(pivotRows, [])
.reduce(buildObject, {});
console.log(detect(exampleString));
If you look at detect, it's just executing a series of functions on the string. The first one just splits it by line-breaks. I liked what you were going for with the countBar variables, but this seemed easier.
That gives us a bunch of string arrays, which need to be broken down into columns. Here, I used some RegEx to separate everything between a combination of space and |. In cleanColumn(), I remove the remaining |s in case there are any stragglers, then replace the spaces with underscores so they can be used as object keys.
Then, remove the empty strings with the .filter(Boolean) trick (link). The last two functions are probably more verbose than necessary, but they do the job. pivotRows() uses the row and column indexes to pivot columns into rows. Last, in buildObject() the first element of each of the rows is added as the key of an object, with the rest of the values being pushed into string arrays.
Really, you should probably just use csvtojson.
Here's an attempt at just splitting by |.
var text = `| market | payment type | customer type | translation |
| NZ | AAA | BBB | NZ |
| AZ | CCC | DDD | AZ |
| CA | EEE | FFF | CA |`;
var result = {
payment: text.split('|').filter((f, i) => i-7 >= 0 && (i - 7) % 5 == 0)
.map(p => p.trim()),
customer: text.split('|').filter((f, i) => i-8 >= 0 && (i - 8) % 5 == 0)
.map(p => p.trim())
}
console.log(result)

Read Digital Numbers in JavaScript (Node.js)?

I have a text file in which digital characters are there like -
_ _ _ _ _ _ _ _ _ (line 1)
| _| _||_||_ |_ ||_||_| (line 2)
||_ _| | _||_| ||_| _| (line 3)
(line 4)
_ _ _ _ _ _ _ (line 5)
|_||_|| ||_||_ | | ||_ (line 6)
| _||_||_||_| | | | _| (line 7)
(line 8)
Invoice number format:
Each invoice number is constructed of 9 digits [0..9]
Invoice number is written using _ and | characters.
Invoice number input takes 4 lines.
The first 3 lines contain 27 characters.
The fourth line is blank.
The output should be -
723956789
490867715
I read the text file using fs module of node js like this and break every digital character in to three parts basically -
var fun = function(){
fs.readFile("./input1.txt", 'utf8', function(err, data) {
var i = 0;
console.log(data.length);
while(data[i] != "\n" && i<data.length) {
if(data[i] != " ") {
var str = "";
while(data[i]!= " " && data[i]!= "\n") {
str = str + data[i];
i++;
}
inputA.push(str);
} else {
i++;
}
}
i++;
console.log(i,inputA);
while(data[i] != "\n" && i<data.length) {
if(data[i] != " ") {
var str = "";
while(data[i]!= " " && data[i]!= "\n") {
str = str + data[i];
i++;
}
inputB.push(str);
// console.log(inputA);
} else {
i++;
}
}
i++;
console.log(i,inputB);
while(data[i] != "\n" && i<data.length) {
if(data[i] != " ") {
var str = "";
while(data[i]!= " " && data[i]!= "\n") {
str = str + data[i];
i++;
}
console.log(str);
inputC.push(str);
// console.log(inputA);
} else {
i++;
}
}
console.log(inputA);
console.log(inputB);
console.log(inputC);
})
}
But not able to read properly. Can any one help me to read and get the desired output.
Here are two functions in ES6 which do the job:
function getDigit(pattern) {
return {
" _ | ||_|": 0,
" | |": 1,
" _ _||_ ": 2,
" _ _| _|": 3,
" |_| |": 4,
" _ |_ _|": 5,
" _ |_ |_|": 6,
" _ | |": 7,
" _ |_||_|": 8,
" _ |_| |": 9,
" _ |_| _|": 9, // alternative 9
}[pattern];
}
function getNumber(lines) {
// Chop each line into 9 pieces of 3 chars:
lines = lines.map( line => line.match(/.../g) );
// Combine the pieces of each digit-pattern together:
return +lines[0].map ( (piece, i) => piece + lines[1][i] + lines[2][i] )
// Translate each pattern of 3x3=9 characters to a digit
.map(getDigit)
// Join digits together into one number
.join('');
}
// Sample data
const data =
' _ _ _ _ _ _ _ _ _ \n'
+ ' | _| _||_||_ |_ ||_||_|\n'
+ ' ||_ _| | _||_| ||_| _|\n'
+ '\n'
+ ' _ _ _ _ _ _ _ \n'
+ '|_||_|| ||_||_ | | ||_ \n'
+ ' | _||_||_||_| | | | _|';
const lines = data.split('\n');
var a = getNumber(lines.slice(0, 3));
var b = getNumber(lines.slice(4));
console.log(a);
console.log(b);
As Timo stated in the comments, it would be far preferable to ask whomever produced the text file to export their data in a sane format.
If this is not possible, here is one way to translate the numbers into something usable, though I have taken the liberty of changing the format of your first 9 to match the two other nines in your sample input.
If the 9s can be in two different formats, I would simply use a Map to catch both formats.
// Note the first 9 in the first number has been changed.
let input = `
_ _ _ _ _ _ _ _ _
| _| _||_||_ |_ ||_||_|
||_ _| _| _||_| ||_| _|
_ _ _ _ _ _ _
|_||_|| ||_||_ | | ||_
| _||_||_||_| | | | _|
`;
// Strip empty lines
let lines = input.split('\n').filter(Boolean);
// Format: line1 + line2 + line3
let translator = [
' _ | ||_|', //0
' | |', //1
' _ _||_ ', //2
' _ _| _|', //3
' |_| |', //4
' _ |_ _|', //5
' _ |_ |_|', //6
' _ | |', //7
' _ |_||_|', //8
' _ |_| _|', //9, or ' _ |_| |' if the other 9 format was correct
]
let nums = [];
// Each "number" is 3 lines long.
for (let i = 0; i < lines.length; i += 3)
{
let num = 0;
// There are 9 numbers per line, 3 characters per number per line
for (let n = 0; n < 27; n += 3)
{
let s = lines[i].substr(n, 3) + lines[i + 1].substr(n, 3) + lines[i + 2].substr(n, 3);
num = num * 10 + translator.indexOf(s);
}
nums.push(num);
}
console.log(nums[0] == 723956789, nums[0]);
console.log(nums[1] == 490867715, nums[1]);

regular expression for ip v4

I am doing an ip v4 validator program with javascript.
The ip has to be between the range of 1.0.0.0 to 255.255.255.255
My problem is that I also get the 0.0.0.0 and should not take it.
I leave you my regular expression:
Var Expression1 = new RegExp ("[0-9] | [1-9] [0-9] | 1 [0-9] {2} | 2 [0-4] [0-9] | 25 [0-5]) [3] ([0-9] | [1-9] [0-9] | 1 [0-9] {2} | 2 [0-4] [0-9] ] | 25 [0-5]) $ ");
Thank you!
Add "not 0.0.0.0" negative lookbehind (^(?!0\.0\.0\.0)) at the beginning of the line:
^(?!0\.0\.0\.0)(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$
Demo: https://regex101.com/r/dIkHRJ/2
P.S.
Please notice your regex is incomplete and broken. Use the corrected one from the sample above.
Why not use a function, it will be clearer not using a regex:
function validateIP(ip) {
var p = ip.split('.'); // split it by '.'
if(p.length !== 4) return false; // if there is not for parts => false
for(var i = 0; i < 4; i++) // for each part
if(isNaN(p[i]) || i < 0 || i > 255) return false; // if it's not a number between 0 - 255 => false
return p[3] > 0; // return true if the last part is not 0, false otherwise
}
alert(validateIP(prompt("IP: ")));
The more accurate solution using RegExp.prototype.test(), String.prototype.split() and Array.prototype.every() functions:
var re = /^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/,
validateIPv4 = function(ip) {
return re.test(ip) && ip.split('.').every(function(d, idx){
var octet = Number(d);
if (idx === 0) {
return octet > 0;
}
return 0 <= octet && octet <= 255;
});
};
console.log(validateIPv4('0.0.0.0'));
console.log(validateIPv4('1.0.0.0'));
console.log(validateIPv4('127.0.0.1'));
console.log(validateIPv4('255.255.255.255'));

Regular Expression doesn't count characters that are part of * quantifier

the regular expression: /([a-z][0-9]*){6,12}/i
so i am expecting this to return true if a string contains more than 6 and less than 12 characters even if there aren't 6 alphabetical characters, but it doesn't, i want "123456789a" to return true and "abcdefghi1", but the first one doesn't.
var myRegEx = /([a-z][0-9]*){6,12}/i;
function checkIt() {
var myString = document.getElementsByTagName("input")[0].value;
if(myRegEx.test(myString) == true) {
document.getElementsByTagName("p")[0].className = "trueOrFalse true";
document.getElementsByTagName("p")[0].innerHTML = "True";
}
else {
document.getElementsByTagName("p")[0].className = "trueOrFalse false";
document.getElementsByTagName("p")[0].innerHTML = "False";
}
}
https://jsfiddle.net/y71mudms/2/
the correct regex is
var myRegEx = /^[0-9]{6,11}[a-z]{1}$/i;
we search exact match of digits + 1 char from 6 to 12
/^[0-9]{6,11}[a-z]{1}$/i;
^ ^ ^ ^
| | | |_ end of string
| | |
| | |_ from 6 min to 11 max repetitions
| |
| |_ digit 0-9 include all digits
|
|_ begin of string
ref. 6 digits regular expression
Just wrap a check for the string-length around your regex-conditions:
if string.length > 6 && string.length < 12) {
// if regex...
}

Categories