Clip off last digits from arrays - javascript

I have the following array
var arr = ['1234','23C','456','356778', '56']
I want to remove array elements which are less than 3 characters and greater than 4 characters. The final result should be as follows
arr = ['1234', '23C', '456']; //only 3 and 4 digits in the array.
Secondly, I want to do the following. if 'arr' has elements longer than 3 characters, I need to clip of by removing the last digit. The final 'data' array should look like this.
arr = ['123', '23C', '456'];

For the first part, you can just use filter to filter out numbers that aren't composed of 3 digits.
var arr = [1234, 234, 456, 356778, 56];
var result = arr.filter(function(num) {
return num < 1000 && num >= 100;
});
console.log(result);
For the second part, you can use map. Just convert the number to a string. If the length of it is greater than 3, take the substring composed of the first 3 elements of the string, then convert back to a number.
var data = [1234, 123, 4567, 3333];
var result = data.map(function(num) {
num = num.toString().substring(0, 3);
return parseInt(num);
});
console.log(result);

All You want is Array.filter and Array.map, and converting String to Number
var arr = [1234,234,456,356778, 56]
var newArr = arr.filter((num) => {
// convert number to string
var str = '' + num
// if length is 3 or 4 - return true (element will be in newArr)
return str.length === 3 && str.length === 4
})
and the second case
var newArr = arr.map((num) => {
var str = '' + num
// is str is longer than 3, cut it to length of 3
if(str.length > 3)
str = str.substring(0, 3)
// return str converted to number
return +str
})

function filterArray(arr,lowDigits,highDigits){
var newArr=[];
for(i=0;i<arr.length;i++){
val=arr[i];
length=val.length;
if(length>=lowDigits&&length<=highDigits){
if(length>lowDigits){
val=val.substring(0,lowDigits);
}
newArr.push(val);
}
}
return newArr;
}
var arr = ['1234','234','456','356778','56'];
arr=filterArray(arr,3,4);
console.log(arr);

To handle if a number is 3 or 4 digits, check if each number is in the range 100 <= num < 10000
let result = arr.filter(function(val) {
// is a 3 or 4 digit number
return 100 >= val && num < 10000;
});
To clip the four digits to 3 digits, we can divide all four digit numbers by 10 and convert them to an integer
let clippedResult = result.map(function(val) {
return val >= 1000 ? Math.floor(val / 10) : val
});

This solution converts the input array to a string of the form 1234,23C,456,356778,56, then finds the wanted elements using regexp.
var arr = ['1234','23C','456','356778', '56'];
console.log(String(arr).match(/\b\w{3}(?=\w?\b)/g));
In English:
Find all the substrings which start with a word boundary (\b, which will be after a comma, or the beginning of the string), then have three alphanumeric characters, and which looking ahead ((?=) may (?) have one additional character before the next word boundary (comma or end of string).
And yes, this will work with string elements, as long as the strings are composed of alphanumerics (in other words, things which won't break the word break (\b) logic.

let isValidElement = updated_ImportDetails.ImportData.filter(function (num) {
// is a 3 or 4 digit number
return num.length > 2 && num.length <4 ;
});
var result = isValidElement.map(function (num) {
num = num.substring(0, 3);
return num;
});
result = result.filter(function (elem, index, self) {
return index == self.indexOf(elem);
}) //removes duplicates from the array
This worked for me.

Related

How to convert a long string (more than 16 digits) into numbers

this is a function just increment one number into array
but the problem i interface when i put alot of numbers into array (more than 16 digits)
when i use parseInt() just returned 16 correct numbers and more than that be zero
6145390195186705000
and expected
6145390195186705543
the function
var plusOne = function(digits) {
var numbersInString = digits.join('');
var theNumbers = parseInt(numbersInString);
var theNumbersPlusOne = theNumbers + 1;
var result = String(theNumbersPlusOne).split("").map((theNumbersPlusOne) => {
return Number(theNumbersPlusOne);
});
return result;
};
console.log(plusOne([6,1,4,5,3,9,0,1,9,5,1,8,6,7,0,5,5,4,3]));
Just expanding on my above comment with another solution...
You've exceeded the maximum safe integer value. (Number.MAX_SAFE_INTEGER, which equals 9007199254740991). Numbers larger than this are not supported with standard integer types in javascript, or rather there's not enough precision to represent them. Anything larger than this is represented in scientific notation and the extra digits are truncated and represented only as zeroes.
With that said, you don't even need to convert the array to a string to an integer just to increment it. You can just increment the individual digits in the array, starting at the end and working your way forwards to "carry the 1" so to speak.
var plusOne = function(digits) {
for(let i = digits.length - 1; i > -1; i--)
{
if(digits[i] == 9)
{
digits[i] = 0;
if(i == 0)
digits = [1].concat(digits);
}
else
{
digits[i]++;
break;
}
}
return digits;
};
console.log(plusOne([6,1,4,5,3,9,0,1,9,5,1,8,6,7,0,5,5,4,3]));
You can use BigInt to handle this problem.
var plusOne = function(digits) {
var numbersInString = digits.join('');
var theNumbers = BigInt(numbersInString);
var theNumbersPlusOne = theNumbers + BigInt(1);
var result = theNumbersPlusOne.toString().split("").map((theNumbersPlusOne) => {
return Number(theNumbersPlusOne);
});
return result;
};
console.log(plusOne([6,1,4,5,3,9,0,1,9,5,1,8,6,7,0,5,5,4,3]));

How to build a function that searches for string occurrences?

I need help Writing a function subLength() that takes 2 parameters, a string and a single character. The function should search the string for the two occurrences of the character and return the length between them including the 2 characters. If there are less than 2 or more than 2 occurrences of the character the function should return 0. How can I solve this problem using loops?
subLength('Saturday', 'a'); // returns 6
subLength('summer', 'm'); // returns 2
subLength('digitize', 'i'); // returns 0
subLength('cheesecake', 'k'); // returns 0
Here I loop through the characters of the string to find each value that is the char.
if the length isn't 2, return 0.
using slice, get only the characters within the two found indexs and get that length adding one to fix the offset
const subLength = (str, char) => {
let strChars = str.toLowerCase().split(""),
found = [],
length = 0;
strChars.forEach((val, index) => {
if (val === char) {
found.push(index);
}
});
if (found.length != 2) {
return length;
}
return str.slice(found[0], found[1]).length + 1;
}
console.log(subLength('Saturday', 'a')); // returns 6
console.log(subLength('summer', 'm')); // returns 2
console.log(subLength('digitize', 'i')); // returns 0
console.log(subLength('cheesecake', 'k')); // returns 0
You can try this logic:
Loop over string and count number of occurance
if count is 2,
Create a regex to capture the string in between.
Return its length
Else return 0
function subLength(str, char) {
let length = 0;
const occuranceCount = Array
.from(str)
.filter((c) => c.toLowerCase() === char.toLowerCase())
.length
if (occuranceCount === 2) {
const regex = new RegExp(`${char}(.*)${char}`)
length = str.match(regex)[0].length
}
console.log(length)
return length;
}
subLength('Saturday', 'a'); // returns 6
subLength('summer', 'm'); // returns 2
subLength('digitize', 'i'); // returns 0
subLength('cheesecake', 'k'); // returns 0
Using just for loop:
function subLength(str, char) {
let count = 0;
let initPosition;
let lastPosition;
for (let i = 0; i < str.length; i++) {
if (str[i] === char) {
count++
if (count > 2) {
return 0;
}
if (initPosition === undefined) {
initPosition = i
} else {
lastPosition = i+1
}
}
}
return count < 2 ? 0 : lastPosition - initPosition;
}
console.log(subLength('Saturday', 'a')); // returns 6
console.log(subLength('summer', 'm')); // returns 2
console.log(subLength('digitize', 'i')); // returns 0
console.log(subLength('cheesecake', 'k')); // returns 0
I too am going through the Codecademy course where this question came up which led me to this post.
Using the RegExp solution provided by #Rajesh (thank you!!) I started to break it down to better understand what was going on and making notes/comments because I am still pretty new and haven't used or been exposed to some of these things.
At the end of it all I thought I'd share what I ended up with in case anyone found it helpful.
function subLength(str, char) {
// Outputting to the console what we are looking for given the value of the string and character from the test cases at the end of this script.
console.log(`Showing the subLength for the string: "${str}" between "${char}" and "${char}" including the "${char}" positions.`);
// create the length variable which will be returned by the function
let length = 0;
// ** Search the string for the two occurrences of the character and count them. Then assign the result to the occurrenceCount variable for use in the if else statement.
// The "Array" class is a global object that is used in the construction off arrays.
// The Array.from() static method creates a new, shallow-copied Array instance from an array-like or iterable object.
// The Array.filter() method creates a new array with all elements that pass the test implemented by the provided function. The "c" represents each element of the array/string which is then compared to the char variable. if it is a match it gets added to the Array. We use .toLowerCase on both to ensure case compatibility.
// Appending the Array with ".length" assigns occurrenceCount the numeric value of the array's length rather than the array of characters.
const occurrenceCount = Array.from(str).filter((c) => c.toLowerCase() === char.toLowerCase());
console.log(' The contents of the occurrenceCountArray = ' + occurrenceCount);
console.log(' The character occurrence count = ' + occurrenceCount.length);
// if the string has two occurrences : return the length between them including the two characters : else the string has less than 2 or more than 2 characters : return 0.
if (occurrenceCount.length === 2) {
// The RegExp object is used for matching text with a pattern. The "(.*)" in between the ${char}'s will match and capture as much as possible aka greedy match. "()" = capture anything matched. (" = start of group. "." = match any character. "*" = Greedy match that matches everything in place of the "*". ")" = end of group.
const regex = new RegExp(`${char}(.*)${char}`);
// log to console the pattern being matched
console.log(` regex pattern to find = ${regex}`);
// log to the console the [0] = index 0 pattern that was captured from the string using str.match(regex)[0]
console.log(` regex output = ${str.match(regex)[0]}`);
// Use".length" to count the number of characters in the regex string at index 0 of the regex array and assign that value to the length variable.
length = str.match(regex)[0].length;
// Output the results to the console
console.log(` The distance from "${char}" to "${char}" (including the "${char}" positions) in the string: ${str} = ${length}\n`);
// return the length value
return length;
} else {
// Output the results to the console
console.log(` The string either has too many or too few occurrences.\n The subLength = ${length}\n`);
// return the length value
return length;
}
}
// test cases
subLength('Saturday', 'a'); // returns 6
subLength('summer', 'm'); // returns 2
subLength('digitize', 'i'); // returns 0
subLength('cheesecake', 'k'); // returns 0
The answer I am getting is this:
const subLength = (str, char) => {
let charCount = 0;
let len = -1;
for (let i=0; i<str.length; i++) {
if (str[i] == char) {
charCount++;
if (charCount > 2) {
return 0;
}
if (len == -1) {
len = i;
} else {
len = i - len + 1
}
}
}
if (charCount < 2) {
return 0;
}
return len;
};
It is better to try yourself a solution first. It is a very bad practice to just ask a solution for your homework!!!
Even if the solution can be JUST a few lines of code i wrote for you with commments a working solution :
const subLength = (str,char) => {
// create an empty array
const strarr = [];
// push string into array
strarr.push(str);
//initiate a count variable
let count = 0;
// WRITE YOUR REGULAR EXPRESSION
// Using the regular expression constructor - new RegExp("ab{2}", "g") .
const regString = `[${char}]`;
const regex = new RegExp(regString, "g");
// iterate through the string array to
for (let i = 0; i < strarr.length; i++) {
// calculate how many time the character occurs
count = (strarr[i].match(regex) || []).length;
};
// check with if condition
//if count is 2
if (count === 2) {
// calculate the index of first ocurrance of the string
first = str.indexOf(char);
// calculate the index of second ocurrance of the string
second = str.lastIndexOf(char);
// calculate the distance between them
return second - first + 1;
// if count is greater than two return 0
}
else if (count > 2) {
return count = 0;
}
// if count is less than two return 0
else if (count < 2) {
return 0;
}
};
console.log(subLength("iiiiliiile","l"));
I just answered this problem in codeAcademy and this is the solution that I came up with, just using if-statements and string.indexOf
const subLength = (strng, char) => {
let firstIndex = strng.indexOf(char);
let secondIndex = strng.indexOf(char, (firstIndex + 1));
let thirdIndex = strng.indexOf(char, (secondIndex + 1));
if (firstIndex === -1){
return 0
} else if (secondIndex === -1){
return 0
} else if (thirdIndex === -1 ){
return (secondIndex - firstIndex + 1)
} else {
return 0
};
};

How to find characters of a string that did not changed position after resverse

I want to know how can I print the number of characters of a string that does not change its position after reversal of that string in JavaScript.
Is there any way?
data stream - alphxxdida . After reverse - adidaxxhpla. so here x and a doesn't changed it position. How can I do this ?
Input - alphxxdida
Output-4
A character doesn't change upon reverse if the character in the "mirror image" position is the same character. The "mirror image" position of a character n positions from the start of the string is the character n positions from the end of the string.
let mirroredChars = str => {
let result = [];
let halfLen = Math.ceil(str.length / 2);
let lastIndex = str.length - 1;
for (let i = 0; i < halfLen; i++) {
if (str[i] === str[lastIndex - i]) result.push(str[i]);
}
return result;
};
console.log(mirroredChars('alphxxdida'));
The count is actually slightly unintuitive. We can't simply take 2 * mirroredChars(...).length, since that would imply the number of mirrored characters is always even (and odd counts can occur, in any odd-length input string, since the middle character can always be considered mirrored).
The count will be:
let countMirroredChars = str => {
let numMirrored = mirroredChars(str).length;
return (str.length % 2) // "Is the input string of odd length?"
? (numMirrored * 2 - 1)
: (numMirrored * 2);
};
We can use a bitwise trick to shorten this code. Either of the following work (and the second should deliver better performance, but looks a bit mystical):
let countMirroredChars = str => mirroredChars(str).length * 2 - str.length % 2;
let countMirroredChars = str => mirroredChars(str).length * 2 - str.length & 1;
You can filter over the characters of the string and compare with the character at the corresponding index in the reversed string. The length of the filtered array will be the number of characters that remained the same.
var str = "alphxxdida";
var reversed = [...str].reverse().join('');
const same = [...str].filter((char,i)=>char===reversed[i]);
console.log(same.length);
Of course, you don't actually need the reversed string to perform the filter, as you can calculate the index of the mirrored character.
var str = "alphxxdida";
var same = [...str].filter((char,i)=>char===str[str.length - i - 1]);
console.log(same.length);
Here is with reduce. Traverse till half length of string and compare the chars from both ends of string and count.
Update: As #Gershom pointed out, Fixed to work for odd length of string.
const getCount = (str) =>
[...str.slice(0, str.length / 2)].reduce(
(acc, char, i) => acc + (char === str[str.length - 1 - i] ? 2 : 0),
str.length % 2
);
var str = "alphxxdida";
var str2 = "alphxdida";
console.log(str, getCount(str));
console.log(str2, getCount(str2));

Having trouble re-indexing my array after looping from the end of the array while adding characters in place

I am trying to solve this particular algorithm question:
You are given a license key represented as a string S which consists only alphanumeric character and dashes. The string is separated into N+1 groups by N dashes.
Given a number K, we would want to reformat the strings such that each group contains exactly K characters, except for the first group which could be shorter than K, but still must contain at least one character. Furthermore, there must be a dash inserted between two groups and all lowercase letters should be converted to uppercase.
Given a non-empty string S and a number K, format the string according to the rules described above.
Example 1:
Input: S = "5F3Z-2e-9-w", K = 4
Output: "5F3Z-2E9W"
Explanation: The string S has been split into two parts, each part has 4 characters.
Note that the two extra dashes are not needed and can be removed.
Example 2:
Input: S = "2-5g-3-J", K = 2
Output: "2-5G-3J"
Explanation: The string S has been split into three parts, each part has 2 characters except the first part as it could be shorter as mentioned above.
Note:
The length of string S will not exceed 12,000, and K is a positive integer.
String S consists only of alphanumerical characters (a-z and/or A-Z and/or 0-9) and dashes(-).
String S is non-empty.
I have written the following code:
const licenseKeyFormatting = (S, K) => {
//convert to array, remove special characters, and capitalize
let s = [...S.replace(/\W/g, '').toUpperCase()]
let pos = 1
//from end of array add '-' for every K
for (let i = s.length - 1; i > 0; i--) {
if (pos === K) {
s.splice(i, 0, '-')
pos = 1
i-- //re-index bc adding to the array
}
pos++
}
return s
}
console.log(licenseKeyFormatting("5F3Z-2e-9-w", 4)) //5F3Z-2E9W
console.log(licenseKeyFormatting("2-5g-3-J", 2)) //2-5G-3J
console.log(licenseKeyFormatting("a-a-a-a-", 1)) // this test case fails should be A-A-A-A, I am getting AAA-A
I am pretty sure the flaw in my logic is due to the re-index, but I can't figure out how to address it.
You should not alter the index. Using splice to insert an element pushes the other elements back, however since you iterate from back to front that doesn't matter. You've already handled the shifted elements.
Another issue is setting pos = 1 in the loop. This is directly followed by pos++. So when pos reaches K the value of pos will be reset to 2 at the end of the loop. Either set pos = 0 (in the loop) so it ends on 1 or move pos++ into the else section.
const licenseKeyFormatting = (S, K) => {
//convert to array, remove special characters, and capitalize
let s = [...S.replace(/\W/g, '').toUpperCase()]
let pos = 1
//from end of array add '-' for every K
for (let i = s.length - 1; i > 0; i--) {
if (pos === K) {
s.splice(i, 0, '-')
pos = 0
}
pos++
}
return s.join("") // <- added join for cleaner console output
}
console.log(licenseKeyFormatting("5F3Z-2e-9-w", 4)) //5F3Z-2E9W
console.log(licenseKeyFormatting("2-5g-3-J", 2)) //2-5G-3J
console.log(licenseKeyFormatting("a-a-a-a-", 1)) // this test case fails should be A-A-A-A, I am getting AAA-A
my way....
function licenseKeyFormatting( S, K )
{
let arr = [...S.replace(/\W/g, '').toUpperCase()]
, p = 0
;
for (let i=arr.length;i--;)
{
p = ++p % K // p = (p+1) % K
if (!p&&i) arr.splice(i,0,'-') // if p===0 and i>0
}
return arr.join('')
}
console.log(licenseKeyFormatting("5F3Z-2e-9-w", 4)) // 5F3Z-2E9W
console.log(licenseKeyFormatting("2-5g-3-J", 2)) // 2-5G-3J
console.log(licenseKeyFormatting("a-a-a-a-", 1)) // A-A-A-A
OR: (more simple)
function licenseKeyFormatting( S, K )
{
let arr = [...S.replace(/\W/g, '').toUpperCase()];
for (let p=arr.length-K;p>0;p-=K) arr.splice(p,0,'-');
return arr.join('');
}
console.log( licenseKeyFormatting("5F3Z-2e-9-w", 4)) // 5F3Z-2E9W
console.log( licenseKeyFormatting("2-5g-3-J", 2)) // 2-5G-3J
console.log( licenseKeyFormatting("a-a-a-a-", 1)) // A-A-A-A

How to separate these strings using javascript

I have collection of string like '36*' , '95' , '103*', '1001*' , '2301'.
I want to separate these into two parts the numerical part into integer and the asterisks part.
eg: take 36 from first, 95 from second, 103 from third and so on. I add them all. If asterisk is found then multiply the number with some factor.
The asterisk is always at the end.
You can extract out the parts you need using a regex.
var values = ['36*', '95', '103*', '1001*', '2301'];
var parts = values.map(function(x) {
var match = /(\d+)(\/|\*|\+|\-)?/.exec(x);
return {
numericPart: match[1],
operator: match[2]
};
});
You can then access the numeric or operator part for each element in your original array. i.e. parts[2].numericPart == 95
The regex (\d+)(\/|\*|\+|\-)? can be broken down as follows;
(\d+) - matches 1 or more digits and stores them in capture group 1
(\/|\*|\+|\-)? - matches a /*+- and stores it in capture group 2, this matches 0 or 1 times
This function will take an input and will return the number & special symbol(*).
function _seperateNum(value){
var returnObj={}; // This object will contain number * special character(if)
var replaceChar="";
if(value.indexOf("*") !=-1){ // check if input has *
replaceChar = value.replace(/[*]/g, ''); // replace it
returnObj.num = parseInt(replaceChar); // convert to number
returnObj.char = "*";
}
else{ // if no special charcater
returnObj.num = parseInt(value);
}
return returnObj;
}
var a =_seperateNum("36*");
console.log(a.num);
Jsfiddle
var
arr = ['36*' , '95' , '103*', '1001*' , '2301'],
sum = 0;
for (var i in arr) {
var item = arr[i];
sum += parseInt(item.indexOf('*') != -1 ? item.replace('*', '') : item);
}
alert(sum);
var arr = ['36*' , '95' , '103*', '1001*' , '2301'];
var t = [];
var f = [];
arr.forEach(function(e){if(e.indexOf("*") > 0){ t.push(e) } else { f.push(e) } } );
console.log(t); //asterisk values
#=> ["36*", "103*", "1001*"]
console.log(f); // other value
#=> ["95", "2301"]
if you want to multiple the each element of the array of asterisk elements to a factor like 10
arr.forEach(function(e){if(e.indexOf("*") > 0){ t.push(parseInt(e)* 10) } else { f.push(parseInt(e)) } } );
console.log(t); //asterisk values
#=> [360, 1030, 10010]
console.log(f); // other value
#=> [95, 2301]

Categories

Resources