I want to extract the last part of this string : "https://steamcommunity.com/profiles/76561198364464404".Just the numbers after '/profiles'.But the problem is the URL can change sometimes.
There are two types of url
1.First one is "https://steamcommunity.com/profiles/76561198364464404" with "/profiles" and then the "id"(id is the numbers after '/profiles').
2."https://steamcommunity.com/id/purotexnuk".Second is this type.Where "/profiles" doesn't exist.
I have come up this code :
let inc;
const index = 27;
const string = 'https://steamcommunity.com/id/purotexnuk';
if (string.includes('profiles')) {
inc = 9;
} else {
inc = 3;
}
console.log(string.slice(index + inc, -1));
The above code checks wheather the string "/profiles" is present.If the string contains "/profiles".inc will be 9.So that slice starts from the right side of the string(url) and ends at the first '/' from the right.inc is 9 becuase "profiles/" length is 9.Similar way if the string(url) contains "id".The slice will start from the end and stop at the first '/' from the right.inc will be 3 becuase "id/" length is 3.
The index is always constant because ,"/profiles" or "/id" only occurs after "https://steamcommunity.com" whose length is 27.Is there any better way i can extract only the profile id or profile name?
(profile id - 76561198364464404)
(profile name - purotexnuk )
You can use regex for this, it will also take care if your url ends with / or has query parameters example https://steamcommunity.com/id/purotexnuk?ref=abc
/.*(?:profiles|id)\/([a-z0-9]+)[\/?]?/i
example:
const regex = /.*(?:profiles|id)\/([a-z0-9]+)[\/?]?/i;
const matches = regex.exec('https://steamcommunity.com/id/purotexnuk');
console.log(matches[1]);
You can split the string with delimiter / and return the last value value from the array;
function getNum(str) {
const arr = str.split('/');
if (!isNaN(arr[arr.length - 1])) {
return arr[arr.length - 1];
}
return ' no number ';
}
const st1 = "https://steamcommunity.com/profiles/76561198364464404";
const st2 = "https://steamcommunity.com/profiles/76561198364464404";
const st3 = "https://steamcommunity.com/id/purotexnuk";
console.log(getNum(st1));
console.log(getNum(st2));
console.log(getNum(st3));
Or do it in one line:
const string = 'https://steamcommunity.com/id/purotexnuk';
console.log(string.slice(string.lastIndexOf("/") + 1, string.length));
Related
I am trying to make a simple encoder in javascript, and copying the output to the clipboard, but the code gives an error.
I tried this code:
function encode() {
let alphabet = " abcdefghijklmnopqrstuvwxyz1234567890-=!##$%^&*()_+[];'/.,'{}|:~";
const a_list = alphabet.split('');
const m_list = prompt("message: ").split('');
let return_message = "";
for (let i = 0; i < m_list.length; i++) {
let current_letter = m_list[i];
let translated_letter = a_list[a_list.indexOf(current_letter) + 5];
return_message += translated_letter;
}
navigator.clipboard.writeText(return_message);
}
encode()
but the console gives this error:
Error: DOMException {INDEX_SIZE_ERR: 1, DOMSTRING_SIZE_ERR: 2, HIERARCHY_REQUEST_ERR: 3, WRONG_DOCUMENT_ERR: 4, INVALID_CHARACTER_ERR: 5, …}
I host the server in replit.
When I try to do an alert with the encoded words, it works fine.
navigator.clipboard.writeText requires a transient user activation. That is why it works when you click on an alert box.
Transient user activation is required. The user has to interact with the page or a UI element in order for this feature to work.
The "clipboard-write" permission of the Permissions API is granted automatically to pages when they are in the active tab.
https://devdocs.io/dom/clipboard/writetext
The error you are getting is because the indexOf function returns -1 when the sought character is not found in the a_list array.
You can check whether the index returned by indexOf is greater than or equal to zero before accessing the element in the a_list array. If the index returned is less than zero, you can simply add the original character to return_message.
Here is an example:
function encode() {
// Define the list of characters to be substituted
const alphabet = "abcdefghijklmnopqrstuvwxyz";
const charList = alphabet.split('');
// Receive the string to be substituted from the user
const inputString = prompt("Enter the string to be substituted:");
// Convert the string to an array of characters
const inputChars = inputString.split('');
// Create a new array with the substituted characters
const outputChars = inputChars.map(char => {
// Find the index of the current character in the character list
const index = charList.indexOf(char.toLowerCase());
// If the character is not in the character list, keep the original character
if (index === -1) {
return char;
}
// Find the next character in the character list
const nextIndex = (index + 1) % charList.length;
const nextChar = charList[nextIndex];
// Return the next substituted character
return char.toUpperCase() === char ? nextChar.toUpperCase() : nextChar;
});
// Convert the array of characters back to a string
const outputString = outputChars.join('');
// Display the substituted string in the console
navigator.clipboard.writeText(outputString);
}
encode()
And as answered in #dotnetCarpenter reply navigator.clipboard.writeText requires a transient user activation. That's why it works when an alert box is clicked.
I have the following problem statement:
Write a function, uncompress, that takes in a string as an argument.
The input string will be formatted into multiple groups according to
the following pattern:
number + char
for example, '2c' or '3a'.
The function should return an uncompressed version of the string where
each 'char' of a group is repeated 'number' times consecutively. You
may assume that the input string is well-formed according to the
previously mentioned pattern.
test_00: uncompress("2c3a1t"); // -> 'ccaaat'
Here is my code which is using a stack. The problem is that it's only returning 'cc' and I can't figure out why. I've console logged what goes into the IF ELSE and I'm hitting both so I don't understand why nothing gets pushed to the stack.
Would really appreciate the help if someone can spot what I'm missing.
const uncompress = (s) => {
const nums = '23456789';
const stack = [];
for (let char of s) {
if (nums.includes(char)) {
stack.push(Number(char));
} else {
const num = stack.pop();
stack.push(char.repeat(num));
};
};
return stack.join('');
};
console.log(uncompress("2c3a1t")); // -> 'ccaaat'
Here's how I would do it:
Split the string up into pairs of numbers and chars:
str.match(/\d+[a-zA-Z]/g)
And reduce that array to a string, while taking each value from the array, getting the char from it (cv.match(/[a-zA-Z]/)[0]) and repeating it according to the number (.repeat(parseInt(cv)))
const uncompress = str => str.match(/\d+[a-zA-Z]/g).reduce((acc, cv) =>
acc + cv.match(/[a-zA-Z]/)[0].repeat(parseInt(cv)), "")
console.log(uncompress("2c3a1t"))
console.log(uncompress("27b1d8g"))
And just like that I was able to write the code which passed the test case:
const nums = '123456789';
const stack = [];
for (let char of s) {
if (nums.includes(char)) {
stack.push(Number(char));
} else {
let num = '';
while (nums.includes(stack[stack.length - 1])) {
num += stack.pop();
}
stack.push(char.repeat(num));
};
};
return stack.join('');
};
My goal is to edit the string (which has an email) to mask the first part, like say the email is johndoe#abc.com then I should output j*****e#abc.com.
var maskPII = function(S) {
var ans = "";
if(S.includes("#")){
S = S.toLowerCase();
var parts = S.split("#");
var first = parts[0];
for(var i=0;i<parts[0].length;i++){
if(i!=0 && i!=parts[0].length - 1)
first[i] = '*';
}
ans = first +"#" +parts[1];
}else{
}
return ans;
};
However in my loop I can't change the characters to asterisks.
After execution I see value of first still same as parts[0] and has no asterisks, can some one explain why? Also, what would I need to do to modify the variable inside loop?
To answer your question... javascript allows you access values of a string using [] indexing.. but that is read only access... you cannot insert/replace values using that operator.
Ref: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String
When using bracket notation for character access,
attempting to delete or assign a value to these properties will not succeed.
The properties involved are neither writable nor configurable.
(See Object.defineProperty() for more information.)
You need to extract the values you want to keep from the existing string and build up a new string as noted in other answers...
Well, this's what you're looking for, and this will be the output j*****e#abc.com.
var ans = "";
var S = "johndoe#abc.com"; //example
S = S.toLowerCase();
var parts = S.split("#");
var first = "";
for(var i = 0; i < parts[0].length; i++){
if(i != 0 && i != parts[0].length - 1){
first += '*';
}else{
first += parts[0][i];
}
}
ans = first +"#"+ parts[1];
console.log(ans);
Here is the code with your approach:
var maskPII = function(S) {
var ans = "";
if(S.includes("#")){
S = S.toLowerCase();
var parts = S.split("#");
var first = parts[0][0];
for(var i=0;i<parts[0].length;i++){
if(i!=0 && i!=parts[0].length - 1)
first += '*';
}
ans = first + parts[0][parts[0].length - 1] +"#" +parts[1];
}else{
}
return ans;
};
But if i were you i would use:
var mail = "johndoe#abc.com";
mail = mail.replace(/(?<=.)(.+?)(?=.#)/gi, '*'.repeat(mail.split('#')[0].length - 2));
console.log(mail);
You can use the bracket notation on a string (like an array) to get the character at a specific index, but you can't use this to change characters. So first[i] = '*' in your code wont do anything.
Strings in JavaScript are immutable. This means that if you want to change a string, a new string instance will be created. This also means that when you change a string in a for-loop, it can impact performance. (Although in this case the difference wont be noticeable.
)
I would use this code:
function maskPII(str) {
const indexOfAt = str.indexOf('#');
if (indexOfAt <= 2) {
return str;
}
return str[0] + '*'.repeat(indexOfAt - 2) + str.substring(indexOfAt - 1);
}
const email = 'johndoe#abc.com';
console.log(email);
console.log(maskPII(email));
It will look for the index of the # sign. If the index is less or equal than 2, (when not found the index will be -1) it will return the original string.
Otherwise it will get the first character, calculate the amount of asterisks needed (index of the # sign -2) and repeat those and then add the rest of the original string.
The initial string:
initString = '/digital/collection/music/bunch/of/other/stuff'
What I want: music
Specifically, I want any term (will never include slashes) that would come between collection/ and /bunch
How I'm going about it:
if(initString.includes('/digital/collection/')){
let slicedString = initString.slice(19); //results in 'music/bunch/of/other/stuff'
let indexOfSlash = slicedString.indexOf('/'); //results, in this case, to 5
let desiredString = slicedString.slice(0, indexOfSlash); //results in 'music'
}
Question:
How the heck do I accomplish this in javascript in a more elegant way?
I looked for something like an endIndexOf() that would replace my hardcoded .slice(19)
lastIndexOf() isn't what I'm looking for, because I want the index at the end of the first instance of my substring /digital/collection/
I'm looking to keep the number of lines down, and I couldn't find anything like a .getStringBetween('beginCutoff, endCutoff')
Thank you in advance!
your title says "index" but your example shows you wanting to return a string. If, in fact, you are wanting to return the string, try this:
if(initString.includes('/digital/collection/')) {
var components = initString.split('/');
return components[3];
}
If the path is always the same, and the field you want is the after the third /, then you can use split.
var initString = '/digital/collection/music/bunch/of/other/stuff';
var collection = initString.split("/")[2]; // third index
In the real world, you will want to check if the index exists first before using it.
var collections = initString.split("/");
var collection = "";
if (collections.length > 2) {
collection = collections[2];
}
You can use const desiredString = initString.slice(19, 24); if its always music you are looking for.
If you need to find the next path param that comes after '/digital/collection/' regardless where '/digital/collection/' lies in the path
first use split to get an path array
then use find to return the element whose 2 prior elements are digital and collection respectively
const initString = '/digital/collection/music/bunch/of/other/stuff'
const pathArray = initString.split('/')
const path = pathArray.length >= 3
? pathArray.find((elm, index)=> pathArray[index-2] === 'digital' && pathArray[index-1] === 'collection')
: 'path is too short'
console.log(path)
Think about this logically: the "end index" is just the "start index" plus the length of the substring, right? So... do that :)
const sub = '/digital/collection/';
const startIndex = initString.indexOf(sub);
if (startIndex >= 0) {
let desiredString = initString.substring(startIndex + sub.length);
}
That'll give you from the end of the substring to the end of the full string; you can always split at / and take index 0 to get just the first directory name form what remains.
You can also use regular expression for the purpose.
const initString = '/digital/collection/music/bunch/of/other/stuff';
const result = initString.match(/\/digital\/collection\/([a-zA-Z]+)\//)[1];
console.log(result);
The console output is:
music
If you know the initial string, and you have the part before the string you seek, then the following snippet returns you the string you seek. You need not calculate indices, or anything like that.
// getting the last index of searchString
// we should get: music
const initString = '/digital/collection/music/bunch/of/other/stuff'
const firstPart = '/digital/collection/'
const lastIndexOf = (s1, s2) => {
return s1.replace(s2, '').split('/')[0]
}
console.log(lastIndexOf(initString, firstPart))
I need to increment a number in a url, the number is always preceded by page/ so like page/2/ however the url could be constructed any which way and may even contain other numbers.
Here's what I have which works but increments all numbers rather than just the one that follows page/. What do I need to do to limit it to only the number preceded by page/?
let link = '//localhost:3000/insight/page/2/';
let next = link.replace(/\d+/g, function(n){ return ++n });
console.log(next)
//Outputs '//localhost:3001/insight/page/3/'
//Needs to be '//localhost:3000/insight/page/3/'
Here's a codepen for ease: https://codepen.io/matt3224/pen/brrEQB?editors=1111
Thanks so much
SOLUTION by #adeneo
let link = '//localhost:3000/insight/page/2/';
let next = link.replace(/page\/(\d+)\//, (x,y) => `page/${(++y)}/`);
You could look for a following slash and the end of the string and replace the number.
let link = '//localhost:3000/insight/page/2/';
let next = link.replace(/\d+(?=\/$)/g, n => +n + 1);
console.log(next);
Matching any numbers between page/ and / should work, regardless of other numbers or where in the URL it occurs
let link = '//localhost:3000/insight/page/2/';
let next = link.replace(/page\/(\d+)\//, (x,y) => 'page/' + (++y) + '/');
console.log(next)
test( '//localhost:3000/insight/page/2/' );
test( '//localhost:3000/insight/page/2/more/here' );
test( '//localhost:3000/page/2/' );
test( '//localhost:3000/insight/page/2/2/2/2/' );
function test(link) {
var next = link.replace(/page\/(\d+)\//, (x,y) => 'page/' + (++y) + '/');
console.log(next)
}
Search for page/ followed by a digit, then slice out the digit, increment it, and rebuild the string.
let next = link.replace(/page\/\d+/g, function(n){
let num = parseInt(n.slice(5))
num++
console.log(num)
const result = "page/"+num
return result
});`
As I was typing, adeneo did the same steps much more elegantly, but perhaps my answer will help someone see what's going on.