I apologize if this question has been answered somewhere - please point me in the right direction if so. I have read through a bunch of solutions and have not yet cracked it!
Sooo...basically, I need to:
Move the first letter of each word to the end of it, then add "ay" to the end of the word. Leave punctuation marks untouched.
This is my code so far:
function pigIt(str) {
var newStr = str.split(" ");
var changed = newStr.map(function(input) {
return input.substring(1) + input.charAt(0) + "ay";
});
changed = changed.join(" ");
return changed;
}
console.log(pigIt('Pig latin is cool'));
As you can see, the code will work for any input that doesn't include punctuation. Great. Now I need to maybe add a Regex somewhere to exclude punctuation but I don't know where to put it! Please help!!
You could split by the word boundary /(\W+)/ while capturing separator. Transform words only. And then join back.
function pigIt(str) {
var newStr = str.split(/(\W+)/); // ['Pig', ' ', 'latin', ',- ',..]
var changed = newStr.map(function(input) {
if (!/\w/.test(input)) return input // keep non word elements as is
return input.substring(1) + input.charAt(0) + "ay";
});
return changed.join("");
}
console.log(pigIt('Pig latin,- is cool!'));
I think because you are going to want to put the punctuation back in the same place after processing, then you will probably be better of doing it all manually.
Loop the input 1 char at a time and build a 'word buffer', every time you hit a non-letter character then process the word buffer and append the non-letter character too.
function pigIt(str) {
var process = function(s) {
if (s.length < 2) {
return s;
}
return s.substring(1) + s.charAt(0) + "ay";
};
var result = '';
var buffer = '';
for (var i = 0; i < str.length; i++) {
var c = str[i];
if (c.match(/[a-zA-Z]/i)) {
buffer += c;
} else {
if (buffer.length) {
result += process(buffer);
buffer = '';
}
result += c;
}
}
result += process(buffer);
buffer = '';
return result;
}
var output = pigIt('Pig latin is cool.');
console.log(output);
I need to break apart strings in JavaScript into chunks of no greater than 100 characters while maintaining breaks between words. I have a function in my own personal library for chunkifying a string into 100-character sections, but I can't seem to wrap my head around how to adapt it to avoid splitting in the middle of a word. I figure something can be managed using regular expressions or something, but it just isn't coming to me. One caveat to any solution is that it has to be pure JavaScript, no jQuery, and the environment has no access to browser-related globals.
-- EDIT --
Ok, I've written some code, but I'm getting strange results...
function chunkify(str) {
var wsRegEx = /\S/;
var wsEndRegEx = /\s$/;
var wsStartRegEx = /^\s/;
var chunks = new Array();
var startIndex = 0;
var endIndex = 100;
var totalChar = 0;
while (true) {
if (totalChar >= str.length) break;
var chunk = str.substr(startIndex,endIndex-startIndex);
while (wsStartRegEx.test(chunk)) {
startIndex++;
endIndex++;
totalChar++;
chunk = str.substr(startIndex,endIndex-startIndex);
}
if (!wsEndRegEx.test(chunk)) {
while (wsRegEx.test(chunk.charAt(endIndex))) {
endIndex--;
}
chunk = str.substr(startIndex,endIndex-startIndex);
}
chunks.push(chunk);
totalChar += chunk.length;
startIndex = endIndex;
endIndex += 100;
}
return chunks;
}
A previous version I posted wasn't counting chunks correctly, but this version, which does seem to break correctly, is now breaking mid word.
-- EDIT #2 --
I think I got it working great now. This seems to do the trick:
function chunkify(str) {
var wsRegEx = /\S/;
var chunks = new Array();
var startIndex = 0;
var endIndex = 100;
while (startIndex < str.length) {
while (wsRegEx.test(str.charAt(endIndex))) {
endIndex--;
}
if (!wsRegEx.test(str.charAt(startIndex)))
startIndex++;
chunks.push(str.substr(startIndex, endIndex - startIndex));
startIndex = endIndex;
endIndex += 100;
}
return chunks;
}
Is there a cleaner way to do this, or have I gotten this to be about as efficient as it'll get?
I have tried to spec this out for you, so you understand one way it can be done
function chunkify (str) {
var chunks = [];
var startIdx = 0, endIdx;
//Traverse through the string, 100 characters at a go
//If the character in the string after the next 100 (str.charAt(x)) is not a whitespace char, try the previous character(s) until a whitespace character is found.
//Split on the whitespace character and add it to chunks
return chunks
}
Here's a way to do it with regex:
chunks = str.match(/.{1,100}/g);
I am trying to solve a Javascript puzzle. I need to write a function that uses a while loop to add a character to the beginning of string and then on the next loop adds the character to the end of the string and to the beginning on the loop after that. The function takes two parameters a string and a number of characters to add.
So far I have
function padIt(str,n){
//coding here
var newStr = "";
var padding = "*";
var i = 0;
while(i<=n){
if (i%2===0){
newStr = newStr+padding;
} else{
newStr = padding+str;
}
i++;
}
return newStr;
}
I am passing the first two test cases but it won't work properly for the third time through the loop. Expecting "* * a *" for n = 3 but only getting "*a". It has to be a while loop so I don't know if I am not setting the loop up correctly or if I am messing up the variables. Any help is greatly appreciated as I am totally lost.
You can do it by writing code like below,
function padIt(str,n, pad = "*"){
var left = Math.ceil(n/2), right = n - left;
return pad.repeat(left) + str + pad.repeat(right);
}
And this function would print,
console.log("a", 1); // "*a"
console.log("a", 2); // "*a*"
console.log("a", 10); // "*****a*****"
Thing need to be read after implementing this code,
String.prototype.repeat()
You need to comment your newStr+=padding; line.
Here is the refined code,
function padIt(str,n){
//coding here
var newStr = "";
var padding = "*";
var i = 0;
while(i<=n){
i++;
newStr=padding+str;
//newStr+=padding;
}
return newStr;
}
HTH
function padIt(str,n){
while(n>0){
if(n%2 === 0){
str = str + '*';
} else{
str = '*' + str;
}
n--;
}
return str;
}
I have a very simple problem but need a solution that works. I have a node script that opens a text file, loops over each line and chunks the line if its over 140 characters but needs to respect word boundaries. This is what I have so far but the lines come out unaffected. I've also tried _.invoke(lines, function() { splitText(this); }; but this also leaves the lines unaffected. Can anyone suggest another way of doing this?
var args = process.argv.splice(2),
fs = require('fs'),
_ = require('underscore'),
splitText;
splitText = function (textSegment) {
var len = 140, curr = len, prev = 0, output = [], currReverse;
while (textSegment[curr]) {
if (textSegment[curr++] == ' ') {
output.push(textSegment.substring(prev, curr));
prev = curr;
curr += len;
} else {
currReverse = curr;
do {
if (textSegment.substring(currReverse - 1, currReverse) == ' ') {
output.push(textSegment.substring(prev, currReverse));
prev = currReverse;
curr = currReverse + len;
break;
}
currReverse--;
} while (currReverse > prev);
}
}
output.push(textSegment.substring(prev));
return output;
}
text = fs.readFileSync(args[0], 'utf-8');
lines = text.split("\n");
lines = _.filter(lines, function (line) {
return line.length >= 100;
});
lines = _.map(lines, function (line) {
return splitText(line);
});
fs.writeFile(args[0], lines.join("\n"), function (err) {
if (err) throw err;
console.log('test');
});
I don't have any experience with underscore.js, but I do know a fairly straightforward way to fix this without it:
function formatStr(text, len) {
len = len||140;
var i=0,
str, newline, breakpt,
formatted = '';
while (i+len<text.length) {
str = text.substr(i, len);
newline = str.indexOf('\n');
if (newline!=-1) {
formatted += str.substr(0,newline+1);
console.log(i,newline);
i += newline + 1;
continue;
}
breakpt = str.lastIndexOf(' ');
formatted += str.substr(0,breakpt) + '\n';
i+=breakpt+1;
}
// add last line to the end and return; credit to Charly
// for mentioning this was missing.
return formatted + text.substr(i);
}
DEMO
What this loop does is the following:
Store the next 140 characters in a var
test if there are already any newlines in this string
if so, just add that part of the string to the formatted string, and continue from there
get the last index of a space in the string variable
append the part of the string until the next space in the formatted string
finally, return the formatted string.
Kind of an old thread but here's a quick solution.
Try this regex, you can see how it works here: http://regexper.com/#%5E(%5Cr%5Cn%7C.)%7B1%2C140%7D%5Cb
str.match(/^(\r\n|.){1,140}\b/g).join('')
What's the shortest way (within reason) to generate a random alpha-numeric (uppercase, lowercase, and numbers) string in JavaScript to use as a probably-unique identifier?
I just came across this as a really nice and elegant solution:
Math.random().toString(36).slice(2)
Notes on this implementation:
This will produce a string anywhere between zero and 12 characters long, usually 11 characters, due to the fact that floating point stringification removes trailing zeros.
It won't generate capital letters, only lower-case and numbers.
Because the randomness comes from Math.random(), the output may be predictable and therefore not necessarily unique.
Even assuming an ideal implementation, the output has at most 52 bits of entropy, which means you can expect a duplicate after around 70M strings generated.
If you only want to allow specific characters, you could also do it like this:
function randomString(length, chars) {
var result = '';
for (var i = length; i > 0; --i) result += chars[Math.floor(Math.random() * chars.length)];
return result;
}
var rString = randomString(32, '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ');
Here's a jsfiddle to demonstrate: http://jsfiddle.net/wSQBx/
Another way to do it could be to use a special string that tells the function what types of characters to use. You could do that like this:
function randomString(length, chars) {
var mask = '';
if (chars.indexOf('a') > -1) mask += 'abcdefghijklmnopqrstuvwxyz';
if (chars.indexOf('A') > -1) mask += 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
if (chars.indexOf('#') > -1) mask += '0123456789';
if (chars.indexOf('!') > -1) mask += '~`!##$%^&*()_+-={}[]:";\'<>?,./|\\';
var result = '';
for (var i = length; i > 0; --i) result += mask[Math.floor(Math.random() * mask.length)];
return result;
}
console.log(randomString(16, 'aA'));
console.log(randomString(32, '#aA'));
console.log(randomString(64, '#A!'));
Fiddle: http://jsfiddle.net/wSQBx/2/
Alternatively, to use the base36 method as described below you could do something like this:
function randomString(length) {
return Math.round((Math.pow(36, length + 1) - Math.random() * Math.pow(36, length))).toString(36).slice(1);
}
UPDATED:
One-liner solution, for random 20 characters (alphanumeric lowercase):
Array.from(Array(20), () => Math.floor(Math.random() * 36).toString(36)).join('');
Or shorter with lodash:
_.times(20, () => _.random(35).toString(36)).join('');
Another variation of answer suggested by JAR.JAR.beans
(Math.random()*1e32).toString(36)
By changing multiplicator 1e32 you can change length of random string.
Or to build upon what Jar Jar suggested, this is what I used on a recent project (to overcome length restrictions):
var randomString = function (len, bits)
{
bits = bits || 36;
var outStr = "", newStr;
while (outStr.length < len)
{
newStr = Math.random().toString(bits).slice(2);
outStr += newStr.slice(0, Math.min(newStr.length, (len - outStr.length)));
}
return outStr.toUpperCase();
};
Use:
randomString(12, 16); // 12 hexadecimal characters
randomString(200); // 200 alphanumeric characters
This is cleaner
Math.random().toString(36).substr(2, length)
Example
Math.random().toString(36).substr(2, 5)
function randomString(len) {
var p = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
return [...Array(len)].reduce(a=>a+p[~~(Math.random()*p.length)],'');
}
Summary:
Create an array of the size we want (because there's no range(len) equivalent in javascript.
For each element in the array: pick a random character from p and add it to a string
Return the generated string.
Some explanation:
[...Array(len)]
Array(len) or new Array(len) creates an array with undefined pointer(s). One-liners are going to be harder to pull off. The Spread syntax conveniently defines the pointers (now they point to undefined objects!).
.reduce(
Reduce the array to, in this case, a single string. The reduce functionality is common in most languages and worth learning.
a=>a+...
We're using an arrow function.
a is the accumulator. In this case it's the end-result string we're going to return when we're done (you know it's a string because the second argument to the reduce function, the initialValue is an empty string: ''). So basically: convert each element in the array with p[~~(Math.random()*p.length)], append the result to the a string and give me a when you're done.
p[...]
p is the string of characters we're selecting from. You can access chars in a string like an index (E.g., "abcdefg"[3] gives us "d")
~~(Math.random()*p.length)
Math.random() returns a floating point between [0, 1) Math.floor(Math.random()*max) is the de facto standard for getting a random integer in javascript. ~ is the bitwise NOT operator in javascript.
~~ is a shorter, arguably sometimes faster, and definitely funner way to say Math.floor( Here's some info
I think the following is the simplest solution which allows for a given length:
Array(myLength).fill(0).map(x => Math.random().toString(36).charAt(2)).join('')
It depends on the arrow function syntax.
for 32 characters:
for(var c = ''; c.length < 32;) c += Math.random().toString(36).substr(2, 1)
Random character:
String.fromCharCode(i); //where is an int
Random int:
Math.floor(Math.random()*100);
Put it all together:
function randomNum(hi){
return Math.floor(Math.random()*hi);
}
function randomChar(){
return String.fromCharCode(randomNum(100));
}
function randomString(length){
var str = "";
for(var i = 0; i < length; ++i){
str += randomChar();
}
return str;
}
var RandomString = randomString(32); //32 length string
Fiddle: http://jsfiddle.net/maniator/QZ9J2/
Using lodash:
function createRandomString(length) {
var chars = "abcdefghijklmnopqrstufwxyzABCDEFGHIJKLMNOPQRSTUFWXYZ1234567890"
var pwd = _.sampleSize(chars, length || 12) // lodash v4: use _.sampleSize
return pwd.join("")
}
document.write(createRandomString(8))
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.min.js"></script>
Random Key Generator
keyLength argument is the character length you want for the key
function keyGen(keyLength) {
var i, key = "", characters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
var charactersLength = characters.length;
for (i = 0; i < keyLength; i++) {
key += characters.substr(Math.floor((Math.random() * charactersLength) + 1), 1);
}
return key;
}
keyGen(12)
"QEt9mYBiTpYD"
var randomString = function(length) {
var str = '';
var chars ='0123456789ABCDEFGHIJKLMNOPQRSTUVWXTZabcdefghiklmnopqrstuvwxyz'.split(
'');
var charsLen = chars.length;
if (!length) {
length = ~~(Math.random() * charsLen);
}
for (var i = 0; i < length; i++) {
str += chars[~~(Math.random() * charsLen)];
}
return str;
};
When I saw this question I thought of when I had to generate UUIDs. I can't take credit for the code, as I am sure I found it here on stackoverflow. If you dont want the dashes in your string then take out the dashes. Here is the function:
function generateUUID() {
var d = new Date().getTime();
var uuid = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g,function(c) {
var r = (d + Math.random()*16)%16 | 0;
d = Math.floor(d/16);
return (c=='x' ? r : (r&0x7|0x8)).toString(16);
});
return uuid.toUpperCase();
}
Fiddle: http://jsfiddle.net/nlviands/fNPvf/11227/
This function should give a random string in any length.
function randString(length) {
var l = length > 25 ? 25 : length;
var str = Math.random().toString(36).substr(2, l);
if(str.length >= length){
return str;
}
return str.concat(this.randString(length - str.length));
}
I've tested it with the following test that succeeded.
function test(){
for(var x = 0; x < 300000; x++){
if(randString(x).length != x){
throw new Error('invalid result for len ' + x);
}
}
}
The reason i have chosen 25 is since that in practice the length of the string returned from Math.random().toString(36).substr(2, 25) has length 25. This number can be changed as you wish.
This function is recursive and hence calling the function with very large values can result with Maximum call stack size exceeded. From my testing i was able to get string in the length of 300,000 characters.
This function can be converted to a tail recursion by sending the string to the function as a second parameter. I'm not sure if JS uses Tail call optimization
A simple function that takes the length
getRandomToken(len: number): string {
return Math.random().toString(36).substr(2, len);
}
Ff you pass 6 it will generate 6 digit alphanumeric number
Nice and simple, and not limited to a certain number of characters:
let len = 20, str = "";
while(str.length < len) str += Math.random().toString(36).substr(2);
str = str.substr(0, len);
One could just use lodash uniqueId:
_.uniqueId([prefix=''])
Generates a unique ID. If prefix is given, the ID is appended to it.
Here's a simple code to generate random string alphabet.
Have a look how this code works.
go(lenthOfStringToPrint); - Use this function to generate the final string.
var letters = {
1: ["q","w","e","r","t","y","u","i","o","p","a","s","d","f","g","h","j","k","l","z","x","c","v","b","n","m"],
2: ["Q","W","E","R","T","Y","U","I","O","P","A","S","D","F","G","H","J","K","L","Z","X","C","V","B","N","M"]
},i,letter,final="";
random = (max,min) => {
return Math.floor(Math.random()*(max-min+1)+min);
}
function go(length) {
final="",letter="";
for (i=1; i<=length; i++){
letter = letters[random(0,3)][random(0,25)];
final+=letter;
}
return final;
}
I used #Nimphious excellent second approach and found that occasionally the string returned was numeric - not alphanumeric.
The solution I used was to test using !isNaN and use recursion to call the function again.
Why bother? I was using this function to create object keys, if all the keys are alphanumeric everything sorts properly but if you use
numbers as keys mixed with alphanumeric (strings) looping through the object will produce a different order to original order.
function newRandomString(length, chars) {
var mask = '';
if (chars.indexOf('a') > -1) mask += 'abcdefghijklmnopqrstuvwxyz';
if (chars.indexOf('A') > -1) mask += 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
if (chars.indexOf('#') > -1) mask += '0123456789';
if (chars.indexOf('$') > -1) mask += '0123456789';
var result = '';
for (var i = length; i > 0; --i) result += mask[Math.floor(Math.random() *
mask.length)];
/*
we need a string not a number !isNaN(result)) will return true if '1234' or '3E77'
because if we're looping through object keys (created by newRandomString()) and
a number is used and all the other keys are strings then the number will
be first even if it was the 2nd or third key in object
*/
//use recursion to try again
if(!isNaN(result)){
console.log('found a number....:'+result);
return newRandomString(length, chars)
}else{
return result;
}
};
var i=0;
while (i < 1000) {
var a = newRandomString(4, '#$aA');
console.log(i+' - '+a);
//now we're using recursion this won't occur
if(!isNaN(a)){
console.log('=============='+i+' - '+a);
}
i++;
}
console.log('3E77:'+!isNaN('3E77'));//true
console.log('1234:'+!isNaN('1234'));//true
console.log('ab34:'+!isNaN('ab34'));//false
After looking at solutions in answers to this question and other sources, this is the solution that is simplest while allowing for modification of the included characters and selection in the length of the returned result.
// generate random string of n characters
function randomString(length) {
const characters = '0123456789abcdefghijklmnopqrstuvwxyz'; // characters used in string
let result = ''; // initialize the result variable passed out of the function
for (let i = length; i > 0; i--) {
result += characters[Math.floor(Math.random() * characters.length)];
}
return result;
}
console.log(randomString(6));
Use md5 library: https://github.com/blueimp/JavaScript-MD5
The shortest way:
md5(Math.random())
If you want to limit the size to 5:
md5(Math.random()).substr(0, 5)