-1

I have the following Text string:

TEST:ABCDEGF:18:32

The letters in this text varies, it also includes numbers. Target is to extract all letters and numbers excluding : character.

Up until now the following was working for me:

lines.split(":");

Until I stumbled upon a new requirement where we need to extract the time as well in full form 18:32 which means if I use a split it only give me until 18

Now how do I extract this including time which can occur sometimes.

Examples

ABCDED:ERERE:18:32

Desired result:

 temp.fields[0] = ABCDED
 temp.fields[1] = ERERE
 temp.fields[2] = 18:32 
user726720
  • 1,127
  • 7
  • 25
  • 59
  • add more examples of input string and output result – Kamil Kiełczewski Jan 08 '19 at 20:42
  • To add on to what @KamilKiełczewski said, is there any restrictions on how and where time can appear with a colon? – Calvin Godfrey Jan 08 '19 at 20:42
  • If you don't know the number of elements and at which place the time is, then it is not possible. – t.niese Jan 08 '19 at 20:42
  • How are you supposed to distinguish a colon in the string vs a colon as the separator – Bijan Jan 08 '19 at 20:43
  • string.replace()? https://stackoverflow.com/questions/9932957/how-can-i-remove-a-character-from-a-string-using-javascript/9932996 – Robert Harvey Jan 08 '19 at 20:44
  • I think what you want to do is use the array `arr`'s length after it's produced to get the last items in the array. You can get the last item with `arr[arr.length-1]` and the second to last item with `arr[arr.length-2]`. This will give you both values for the time. – hewiefreeman Jan 08 '19 at 20:47
  • TIME: `18:32` always occurs on the last e.g. `fields[2]` in the example – user726720 Jan 08 '19 at 20:48
  • Yes, but if you're using split (which is one of your only options for this) it will also split your time info. You should use `arr.length-1` and `arr.length-2` for the respective values in the array just in case later you might want to add more split info to the string. – hewiefreeman Jan 08 '19 at 20:50
  • 1
    If it only occurs exactly once and is it is always the last element then you are looking for [Split string with limit, where last string contains the remainder](https://stackoverflow.com/questions/25176848) – t.niese Jan 08 '19 at 20:50
  • possible to show examples please – user726720 Jan 08 '19 at 20:52
  • How you will be sure, or trust, for example that "18:32" is representing a time and not representing two separated numbers? – Shidersz Jan 08 '19 at 21:00

5 Answers5

2

If your time is always at the end then you can do something like this.

function doIt(str) {
  var a = str.split(':');
  var b = a.splice(-2) //remove 2 last from a and save in b
    .join(':');
  a.push(b);
  return a;
}

console.log(doIt('TEST:ABCDEGF:18:32'));
Alex Kudryashev
  • 9,120
  • 3
  • 27
  • 36
1

Try this

let str = `TEST:ABCDEGF:18:32:aa:12:BCB:11:12:AAA`;

let m = str.replace(/(\d\d\:\d\d)|\:/g,"$1 ").replace(/ +/g,' ').split(' ');

console.log(m);

Regexp explanation: "\d\d:\d\d" match time on first group, ":" match colon, then we take only first group and space "$1 " as output (so we omit colon, and not matched text will be copy without changes), and then (2nd replace) we change doubled space to 1 space, and then we split all to array.

Kamil Kiełczewski
  • 85,173
  • 29
  • 368
  • 345
  • This looks good is it possible to explain the reg expressions pls – user726720 Jan 08 '19 at 21:11
  • Thanks bro, it's much appreciated. – user726720 Jan 08 '19 at 21:16
  • Does not look really reliable to me `54:12` is not a valid time, what if the column with `aa` or `BCD` holds a two digit number? And it burns an additional letter that cannot be used anymore. – t.niese Jan 09 '19 at 07:04
  • @t.niese I assume that input data are valid (I fix this data-bug in example used in my answer). The validation can be done before or after splitting but Time validation is out of the scope of this question and can be found e.g. [here](https://stackoverflow.com/q/5563028/860099) – Kamil Kiełczewski Jan 09 '19 at 12:36
  • @t.niese if you replace `aa` or `BCD` to 2-digit number then string is invalid bacause you cannot unambiguously determine which digits contains hour. As I write in last comment, I assume that string is valid because OP not mention that It can be invalid so data validation is out of the scope of this question. Explain more about "additional letter" case (on your last comment sentence) - because I don't understand where is the problem – Kamil Kiełczewski Jan 10 '19 at 14:30
1

I resolved it using :

var p2 = parts.slice(3).join(':');

from the following link:

Split string with limit, where last string contains the remainder

This is working as I expect it.

Thanks to t.niese for sharing and thanks to all those who answered. All of these answers work but in the above link it was a simple solution. Unfortunately can't accept all answers. But would love to do so if I had an option. +1 for all

user726720
  • 1,127
  • 7
  • 25
  • 59
  • 1
    I think the only reliable answer (given that you know where the time file occurs), is yours and the one of [Alex Kudryashev](https://stackoverflow.com/a/54099658/1960455). – t.niese Jan 09 '19 at 07:11
  • what contains the `parts` variable in your code? (because I don't know how to run it - if I put there your example string directly, then it doesn't work). The second problem is that as last operation you use `join` - this will return string - not array (as you describe in question) – Kamil Kiełczewski Jan 10 '19 at 00:03
0

You could use replace to modify the delimiter (:) everywhere except when it is between numbers. Something like this:

const data = "ABCDED:ERERE:18:32";

const arr = data.replace(/:/g, function(match, pos, str){
  const before = str.substring(pos - 2, pos);
  const after = str.substring(pos + 1, pos + 3);

  if(!isNaN(before) && !isNaN(after)){
    return match;
  }else {
    return "|";
  }
}).split("|");

console.log(arr);
Titus
  • 22,031
  • 1
  • 23
  • 33
  • These kind of hacks are always really fragile and can have strange results if you where not able to think about all edge cases you could have. E.g. something like that `ab12:12de:12:18:32` would result in `["ABCDED12:12ERERE", "12:18:32"]` – t.niese Jan 09 '19 at 07:08
0

I saw on comments that time appear always at end, so here is my second, simpler answer (text in s)

temp.fields = [...s.slice(0,-6).split(':'), s.slice(-5)]

let s="ABCDED:ERERE:18:32"

let fields =  [...s.slice(0,-6).split(':'), s.slice(-5)]; 

console.log(fields);
Kamil Kiełczewski
  • 85,173
  • 29
  • 368
  • 345