I have a list of numbers
1.01.01.01
1.01.01.02
1.01.02.03
I need to add 1 to the number after the 2nd occurance of '.0':
1.01.02.01
1.01.02.02
1.01.03.03
I am using javascript. I have tried a few things, but I just get so confused with regex haha.
I have been playing, and split might be the way to go here, thanks Richard. Anyone happen to know increment 1
on a 01
in a string, or will I need to break down the string and turn it to an integer. first?
CodePudding user response:
You may use this code snippet that does the job in these steps:
- Splits input string by
.0
- Converts 2nd element to Integer and increments it by 1
- Stores resulting elements in an array
ret
- Joins elements of
ret
with.0
again and saves new String inresult
array - Finally displays
result
array
Code:
const arr = ['1.01.01.01','1.01.01.02', '1.01.02.03'];
const delim = '.0';
var result = [];
arr.forEach(str => {
ret = [];
str.split(delim).forEach((el, i) =>
ret.push(i==2 ? parseInt(el) 1 : el)
);
result.push(ret.join(delim));
});
console.log(result);
<iframe name="sif1" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>
CodePudding user response:
A replace
based approach is in need of a more complex capturing
regex like ... /^((?:.*?\.0){2})(\d )(.*)/
... and a replacer function as its second argument.
The regex ... /^((?:.*?\.0){2})(\d )(.*)/
... reads like this ...
Part 1:
^( (?:.*?\.0){2} )
- From line start
^
capture( ... )
the following match ... (?: ... ){2}
... twice{2}
a not captured?:
group( ... )
of following pattern ....*?0
... anything.*
in a non?
greedy way until a Dot-Zero sequence.0
occurs.
- From line start
Part 2:
(\d )
- Capture
( ... )
at least one\d
.
- Capture
Part 3:
(.*)
- Capture
( ... )
anything.*
greedy until the end of the string.
- Capture
The related replacer function is the callback of replace
and gets passed as arguments the entire match (1st argument) followed by each captured value as separate argument, starting with the first and ending with the last capture.
Thus for the given example the replacer function's argument names (which can be freely chosen) and precedence are ... (match, leading, digits, trailing)
... where digits
is the 2nd capture group, the digit (sequence) which the OP wants to become an incremented integer.
A solution then might look similar to the next provided example code ...
const sampleData = [
'1.01.01.02',
'1.01.02.03',
'1.01.0x.04',
'1.01.0x.0x',
'1.01.001.01.07.08.09',
'1.01.013.03.01200230',
];
// see ... [https://regex101.com/r/60omn1/2]
const regXCapture = (/^((?:.*?\.0){2})(\d )(.*)/);
console.log(
sampleData, '=>',
sampleData.map(item =>
item.replace(
regXCapture,
(match, leading, digits, trailing) => [
leading,
parseInt(digits, 10) 1,
trailing,
].join('')
)
)
);
.as-console-wrapper { min-height: 100%!important; top: 0; }
<iframe name="sif2" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>
A split
and/but non regex based approach can be implemented as straightforward as the following code (of cause having no control over the validity of the parsed 3rd argument which is assumed to be a digit (sequence)) ...
const sampleData = [
'1.01.01.02',
'1.01.02.03',
'1.01.0x.04',
'1.01.0x.0x',
'1.01.001.01.07.08.09',
'1.01.013.03.01200230',
];
console.log(
sampleData, '=>',
sampleData.map(item => {
const [leadingA, leadingB, digits, ...trailing] = item.split('.0');
return [
leadingA, leadingB, (parseInt(digits, 10) 1), ...trailing
].join('.0');
})
);
.as-console-wrapper { min-height: 100%!important; top: 0; }
<iframe name="sif3" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>