11

I have string coming from the server:

//A
123|155-244
  • The first numbers always means 'Red'
  • Numbers after | always means 'Green'
  • Numbers after -always means 'Blue'

The issue here is that Green and Blue can come back in either order:

//B
123-244|155

Or they can be missing entirely:

//C
123|155 

I need a function that returns one array/object to make things easy:

//A
var result = {red:"123", green:"155", blue:"244"}

//B
var result = {red:"123", green:"155", blue:"244"}

//C
var result = {red:"123", green:"155", blue:"0"}

I've tried two functions, one to get Green and the other Blue, but I realized that doesn't work properly depending on the order they appear in the string.

var getGreen = function(myvar){
    return myvar.split('-'); 
};
var getBlue = function(myvar){
    return myvar.split('|'); 
};

Doing this sometimes causes my object to look like this:

var result = {red:"123", green:"155", blue:"244|155"}

How should I proceed?

5
  • 2
    David Bm, can we assume there is always a value for red? Commented Feb 16, 2016 at 9:23
  • Yes, red always come ... blue and green may not come Commented Feb 16, 2016 at 9:24
  • Do you want numbers or number strings? Commented Feb 16, 2016 at 15:55
  • Are the integers always three digits long? How are smaller values represented? Commented Feb 16, 2016 at 15:56
  • i don't mind if they are numbers or strings and the maximum length of the number is 3, it can be lower Commented Feb 16, 2016 at 15:58

8 Answers 8

17

No need for regexes:

parse = function(s) {
    return {
        red:   parseInt('+' + s, 10) || 0,
        green: parseInt(s.split('|')[1], 10) || 0,
        blue:  parseInt(s.split('-')[1], 10) || 0,
    };
};

//

test = [
    '123',
    '222|333-444',
    '55-66|77',
    '123|456',
    '123-456',
    '|123-456',
    '-123|456',
    '010|020-030',
  
];
  
test.map(parse).forEach(r => 
   document.write('<pre>' + JSON.stringify(r) + '</pre>'));

This uses the fact that parseInt stops at the first non-parseable character and returns a falsy value when given garbage. The '+' + s hack is to invalidate the leading dash (which otherwise would be mistaken for the minus sign).

Sign up to request clarification or add additional context in comments.

5 Comments

this looks clean... can regex turn something wrong ?
@DavidBm: regexes are fine, but it's shooting sparrows with cannons in this case.
Since we don't know whether numbers below 100 might have leading zeroes, I'd recommend to always pass the radix 10 to parseInt.
what does the last 2 argument for Stringify() mean?
10

You are probably best using a Regexp to match this - one for each section of the string.

exec() each Regex and the match will be stored in index 1 of the resulting array. If there is no match, then null is returned from exec(), so use a dummy array of [null, 0] simplify things.

Although not a requirement, this also works if there is no red value.

function getRGB() {
  var reRed = /^([0-9]+)/; // start of string (^) then match 1+ numbers
  var reGreen = /\|([0-9]+)/; // a "|" then match 1+ numbers
  var reBlue = /-([0-9]+)/;  // a "-" then match 1+ numbers

  return {
    red: (reRed.exec(input) || [null, 0])[1],
    green: (reGreen.exec(input) || [null, 0])[1],
    blue: (reBlue.exec(input) || [null, 0])[1]
  };
}

// RGB
var input = '123|155-244';
console.log(input, getRGB(input));

// RBG
var input = '123-244|155';
console.log(input, getRGB(input));

// RB
input = '123-244';
console.log(input, getRGB(input));

// BG
var input = '-244|155';
console.log(input, getRGB(input));

Comments

5

You can use String#match with RegEx.

var str = '123|155-244';

var result = {
    red: (str.match(/^\d+/) || [0])[0], // Get first digits or zero
    green: (str.match(/\|(\d+)/) || [0, 0])[1], // Get digits after `|` or zero
    blue: (str.match(/-(\d+)/) || [0, 0])[1] // Get digits after `-` or zero
};

console.log(result);
document.getElementById('pre').innerHTML = JSON.stringify(result, 0, 4);
<pre id="pre"></pre>


Original answer

Misunderstood that - and | are interchangeable, but the sequence of colors will be fixed as Red, Green and then Blue.

You can use String#split with regex.

var str = '123|155-244';
var colors = ['red', 'green', 'blue'];
var result = {};

var arr = str.split(/\||-/g);
arr.forEach((e, i) => result[colors[i]] = arr[i]);

console.log(result);
document.getElementById('result').innerHTML = JSON.stringify(result, 0, 4);
<pre id="result"></pre>

Regex Explanation:

The simple regex \||- will split the string by pipe | or -.

Another live demo:

var colors = ['red', 'green', 'blue'];

document.getElementById('input').addEventListener('keyup', function() {
  var str = this.value;
  var result = {};

  var arr = str.split(/\||-/g);
  arr.forEach((e, i) => result[colors[i]] = arr[i]);
  console.log(result);
  document.getElementById('result').innerHTML = JSON.stringify(result, 0, 4);
}, false);
<input id="input" />

<pre id="result"></pre>

3 Comments

thanks for the anwer, but i need the object to have the three colors on the result, also if the blue is 0
Doesn;t work for blue/green being reversed - 123-244|155
@Rhumborl Right. I thought | and - are interchangable, please check update.
3

You says first number always red so

myString = "123-155|244";
red = "0";
green = "0";
blue = "0";
red = mysString.substring(0,3);
if(myString.indexOf("|")!=-1)
{
  green = mystring.substring(myString.indexOf("|")+1,myString.indexOf("|")+4);
}
if(myString.indexOf("-")!=-1)
{
  blue = mystring.substring(myString.indexOf("-")+1,myString.indexOf("-")+4);
}
console.log(red+green+blue);

Comments

2

You can use string.match(regex):

var str = "123|155-244",  // <--------the string
  arr = str.match(/(\d{3})+/g), // <----creates array out of str
  obj = {
    red: arr[0], // put first one as red value
    green: arr[1], // second one as green value
    blue: arr.length == 3 ? arr[2] : "000" // as per length of array put blue value 
  };

document.querySelector('pre').innerHTML = JSON.stringify(obj);
<pre></pre>

1 Comment

No, the color is not determined by the position of the number but by the character preceding it.
2

You can try this, in end tried testing with all 3 conditions-

function rgbFun(a){
    //Define object either way
    //rgb = {'red':0,'blue':0,'green':0}; 
    rgb = {};
    var r = a.substr(0,3),
        b = a.splitOnLast('-')[1], //will check the last splitted value of blue
        g = a.splitOnLast('|')[1]; //will check the last splitted value of green
    rgb.red = r;
    if(b){
        rgb.blue = b.substr(1,3);
    }else{
        rgb.blue = 0;
    }
    if(g){
        rgb.green = g.substr(1,3);
    }else{
        rgb.green = 0;
    }
    return rgb;
}
rgbFun(CaseA);
//Result - {red: "123", blue: "244", green: "155"}
rgbFun(CaseB);
//Result - {red: "123", blue: "244", green: "155"}
rgbFun(CaseC);
//Result - {red: "123", blue: 0, green: "155"}

Comments

2

may be this is what you want and write some else condition any how you want

var color = {red:null,blue:null,green:null};
var s ="123-244|155";
var blue_index = s.indexOf("|") ;
var green_index = s.indexOf("-") ;
if(blue_index>green_index){
    color.blue = s.split("|")[1];
    s = s.split("|")[0];
}else{
    color.green = s.split("-")[1];
    s = s.split("|")[0];
}
if(s.indexOf("|") > -1){
    color.blue =  s.split("|")[1];
    color.red  =   s.split("|")[0];
}   
if(s.indexOf("-") > -1){
    color.green =  s.split("-")[1];
    color.red  =   s.split("-")[0];
}

Comments

-1

Please try this code HTML :-

<h1 id="red">Red</h1>
<h1 id="green">Green</h1>
<h1 id="blue">Blue</h1>
<input type="submit" id="byBtn" value="Change" onclick="change()"/>

JavaScript:-

 var myvar="123-244|155";
 var getGreen = myvar.split('-');
var getBlue = getGreen[1].split('|');
function change(){
red.innerHTML+=" ="+getGreen[0];
blue.innerHTML+=" ="+getBlue[0];
green.innerHTML+=" ="+getBlue[1];
}

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.