haddow64
haddow64

Reputation: 674

JavaScript substring from string with variable contents

I have a string that can contain various bits of information, I need to substring a GUID from this when I cant be certain of the position of the GUID within the string.

Possible versions of the string

stringVar=email:[email protected]&room:b83edd0d-fec5-4ec0-8055-60bc0d8eb4b6;

stringVar=email:[email protected]&room:b83edd0d-fec5-4ec0-8055-60bc0d8eb4b6&host=HOSTNAME;

stringVar=email:[email protected]&location=SomeCity&room:b83edd0d-fec5-4ec0-8055-60bc0d8eb4b6;

There are a few other permutations of the string with more or less fields, it will always at least contain the GUID.

A rough version of what I have:

var room = str.substring(str.lastIndex(room),str.lastIndex(;))
if room.length !== 36
    var room = str.substring(str.lastIndex(room),str.lastIndexOf(&)

There must be a cleaner way to do this?

Upvotes: 1

Views: 1078

Answers (7)

Jonathan Newton
Jonathan Newton

Reputation: 830

Regex is a good option but it makes the code difficult to read.

var stringValue = "stringVar=email:[email protected]&room:b83edd0d-fec5-4ec0-8055-60bc0d8eb4b6&host=HOSTNAME;"

var pattern = /[\da-zA-Z]{8}-([\da-zA-Z]{4}-){3}[\da-zA-Z]{12}/;

var found = stringValue.match(pattern)

console.log(found[0]);

This code snippet is taking a string value and doing a simple match using a Regex expression, this returns a result array I am simply taking the first index value out of the resulting array.

http://regexr.com/3amuu

Upvotes: 1

Rajesh
Rajesh

Reputation: 24915

I have tried to create a function that would return you an object.

Note: I have changed the format slightly. I have added a city:SomeCity in third format.

Basic format is, you can have = which will have either a string value or an object but not both. So, &host=HOSTNAME is fine, but location=SomeCity&room:b83edd0d-fec5-4ec0-8055-60bc0d8eb4b6 is not and I have changed it to location=city:SomeCity&room:b83edd0d-fec5-4ec0-8055-60bc0d8eb4b6;

Point is value after = should either contain : for every pair or not have it.

Sample

function getObjectFromCookieStr(str){
	var r = {};
  str.split("=").reduce(function(p,c){
  	var k = ''
  	var o = c.split('&').reduce(function(p,c){
    	if(c.indexOf(':') > -1){
      	var kv = c.split(':');
        p[kv[0]] = kv[1]
      }
      else{
      	k=c;
      }
      return p;
    }, {});
    r[p] = Object.keys(o).length >0 ? o : c
    return k;
  });
  return r;
}

var s1 = "stringVar=email:[email protected]&room:b83edd0d-fec5-4ec0-8055-60bc0d8eb4b6"
var s2 = "stringVar=email:[email protected]&room:b83edd0d-fec5-4ec0-8055-60bc0d8eb4b6&host=HOSTNAME";
var s3 = "stringVar=email:[email protected]&location=city:SomeCity&room:b83edd0d-fec5-4ec0-8055-60bc0d8eb4b6";

console.log(getObjectFromCookieStr(s1))
console.log(getObjectFromCookieStr(s2))
console.log(getObjectFromCookieStr(s3))

Now that we have an object, you just have to loop over object to get value. You can use following function to search in object.

function searchKeyInObj(obj, searckKey) {
  if (JSON.stringify(obj).indexOf(searckKey) < 0) return;
  for (var k in obj) {
    if (typeof(obj[k]) === 'object') {
      var v = searchKeyInObj(obj[k], searckKey);
      if (v) return v
    } else if (k === searckKey) {
      return obj[k];
    }
  }
}

You can test it on following JSFiddle

Upvotes: 1

VLAZ
VLAZ

Reputation: 28959

You can just use string manipulation, for example:

var stringVar1 = "email:[email protected]&room:b83edd0d-fec5-4ec0-8055-60bc0d8eb4b6";
var stringVar2 = "email:[email protected]&room:b83edd0d-fec5-4ec0-8055-60bc0d8eb4b6&host=HOSTNAME";
var stringVar3 = "email:[email protected]&location=SomeCity&room:b83edd0d-fec5-4ec0-8055-60bc0d8eb4b6";

function getRoomId(input) {
  return input
    .split("&") //separate into chunks 
    .find(part => part.startsWith("room:")) //see which starts with room
    .split(":")[1]; //split and return the second part, which is the GUID
}
console.log(getRoomId(stringVar1));
console.log(getRoomId(stringVar2));
console.log(getRoomId(stringVar3));

Alternatively a more "dumb" way is to just cut around the string you want. The main disadvantage is that it doesn't look as "fancy" but on the other hand, it will work in all browsers.

var stringVar1 = "email:[email protected]&room:b83edd0d-fec5-4ec0-8055-60bc0d8eb4b6";
var stringVar2 = "email:[email protected]&room:b83edd0d-fec5-4ec0-8055-60bc0d8eb4b6&host=HOSTNAME";
var stringVar3 = "email:[email protected]&location=SomeCity&room:b83edd0d-fec5-4ec0-8055-60bc0d8eb4b6";

function getRoomId(input) {
  return input
    .split("room:")[1] //find the part of the string that starts with "room:" and cut there
    .split("&", 1)[0]; //cut again at the next "&" and return the first part
}
console.log(getRoomId(stringVar1));
console.log(getRoomId(stringVar2));
console.log(getRoomId(stringVar3));

Finally, you can do an even simpler lookup of indeces which will also work in all browsers:

var stringVar1 = "email:[email protected]&room:b83edd0d-fec5-4ec0-8055-60bc0d8eb4b6";
var stringVar2 = "email:[email protected]&room:b83edd0d-fec5-4ec0-8055-60bc0d8eb4b6&host=HOSTNAME";
var stringVar3 = "email:[email protected]&location=SomeCity&room:b83edd0d-fec5-4ec0-8055-60bc0d8eb4b6";

function getRoomId(input) {
  var start = input.indexOf("room:") + 5; //the index is the beginning of "room:", so add 5 characters to get rid of it
  var end = input.indexOf("&", start); //the next "&" after "room:" will be after the GUID
  end = end !== -1? end : input.length; //if there is no next "&", then grab everything until the end of the string
  
  return input.slice(start, end);
}
console.log(getRoomId(stringVar1));
console.log(getRoomId(stringVar2));
console.log(getRoomId(stringVar3));

There are other variations but the idea is that it's simple enough to solve by treating it as a string.

Upvotes: 2

Mamdouh Saeed
Mamdouh Saeed

Reputation: 2324

var str = "email:[email protected]&room:b83edd0d-fec5-4ec0-8055-60bc0d8eb4b6;";
var room = str.split("room:")[str.split("room:").length-1].split("&")[0].split(";")[0];
//b83edd0d-fec5-4ec0-8055-60bc0d8eb4b6

Upvotes: 1

Wiktor Stribiżew
Wiktor Stribiżew

Reputation: 626689

Your 'room' guid only contains hex chars. Use a simple matching regex to capture what you need:

/&room:([a-f\d-]+)/i

and if room may appear as the first field in the string (at its beginning), you can enhance it to match at the start of the string as well:

/(?:^|&)room:([a-f\d-]+)/i
  ^^^^

See the regex demo

Details:

  • &room: - matches the literal char sequence &room: (the (?:^|&) is an alternation group to match either the start string position (^) or (|) the & symbol)
  • ([a-f\d-]+) - matches and captures into Group 1 one or more characters that are ASCII letters in the a-f and A-F ranges (as the /i is a case insensitive mode modifier), digits (\d) or -.

var strngs = ['stringVar=email:[email protected]&room:b83edd0d-fec5-4ec0-8055-60bc0d8eb4b6;', 'stringVar=email:[email protected]&room:b83edd0d-fec5-4ec0-8055-60bc0d8eb4b6&host=HOSTNAME;', 'stringVar=email:[email protected]&location=SomeCity&room:b83edd0d-fec5-4ec0-8055-60bc0d8eb4b6;'];
var re = /&room:([a-f\d-]+)/i;
for (var s of strngs) {
  var res = (m=s.match(re)) ? m[1] : "";
  console.log(s + "\n=>\n" + res); // demo
}

Upvotes: 1

Cristofor
Cristofor

Reputation: 2097

Use this regex

/(room:[a-zA-Z0-9]+\-[a-zA-Z0-9]+\-[a-zA-Z0-9]+\-[0-9]+\-[a-zA-Z0-9]+)/

that would match the following data:

room:b83edd0d-fec5-4ec0-8055-60bc0d8eb4b6  
room:b83edd0d-fec5-4ec0-8055-60bc0d8eb4b6  
room:b83edd0d-fec5-4ec0-8055-60bc0d8eb4b6  

Here is the matching: demo

Upvotes: 1

Mitya
Mitya

Reputation: 34556

There must be a cleaner way to do this?

There is - REGEX.

var guid = str.match(/room:([^&]+)/);

The match, if found, will then live in guid[0], with the guid alone (minus "room:") in guid[1].

Upvotes: 2

Related Questions