Each letter once uppercase - javascript

javascript function which returns an array of string in such a way that it contains all possible upper-case letters of the input string one at a time sequentially.
uppercase("hello") ➞ ["Hello", "hEllo", "heLlo", "helLo", "hellO"]
what i have tried is
const helloCapital = (str) => {
let a = [];
for (let i in str) {
a.push(str[i].toUpperCase() + str.slice(1));
}
return a;
};
but it gives weird results
[ 'Hello', 'Eello', 'Lello', 'Lello', 'Oello' ]

This looks like a challenge for a course or challenges website.
If that is the case, it is really, really not cool to come here and ask for that answer.
But, since I'm already here, here it goes a working solution.
const capitals = s => Array.from(s,(_,i)=>s.slice(0,i)+_.toUpperCase()+s.slice(i+1))
UPDATE: Explaining the code
Array.from works on iterable objects, such as strings, Arrays and, ArrayLike objects for example.
It calls the function you pass as the first argument on each element of the iterable, in this case, the string.
The function receives 1 element of the iterable (the _) and the position of that element (the i)
So the function is returning a concatenation of 3 things:
* the substring of the original string from 0 to i
* the current element of the iterable, or current character, toUpperCase()
* the substring of the original string from i+1 to the end of the string.

Your logic is wrong, to work you need to concat the slice before letter with capitalized letter and with the slice after letter.
function capitalizeEachLetter (text) {
return Array.from(text, (letter, index) =>
text.slice(0, index) + letter.toUpperCase() + text.slice(index + 1)
);
}

use array array map,
var str = "hello";
var capitals = Array.from(str).map((e, i, ar) => {
let r = [...ar];
r[i] = ar[i].toUpperCase();
return r.join('');
});
console.log(capitals)

Related

Trouble understanding .indexOf in this code problem

I recently completed this Leetcode assessment for an open-book interview. Luckily I was able to Google for help, and passed the assessment. I'm having trouble understanding what exactly is happening on the line declared below. I'd love it if one of your smartypants could help me understand it better!
Thank you!
The problem:
Have the function NonrepeatingCharacter(str) take the str parameter being passed, which will contain only alphabetic characters and spaces, and return the first non-repeating character. For example: if str is "agettkgaeee" then your program should return k. The string will always contain at least one character and there will always be at least one non-repeating character.
Once your function is working, take the final output string and combine it with your ChallengeToken, both in reverse order and separated by a colon.
Your ChallengeToken: iuhocl0dab7
function SearchingChallenge(str) {
// global token variable
let token = "iuhocl0dab7"
// turn str into array with .split()
let arrayToken = token.split('')
// reverse token
let reverseArrayToken = arrayToken.reverse();
// loop over str
for (var i = 0; i < str.length; i++) {
// c returns each letter of the string we pass through
let c = str.charAt(i);
***--------------WHAT IS THIS LINE DOING?-------------***
if (str.indexOf(c) == i && str.indexOf(c, i + 1) == -1) {
// create variable, setting it to array with first repeating character in it
let arrayChar = c.split()
// push colon to array
arrayChar.push(':')
// push reversed token to array
arrayChar.push(reverseArrayToken)
// flatten array with .flat() as the nested array is only one level deep
let flattenedArray = arrayChar.flat()
// turns elements of array back to string
let joinedArray = flattenedArray.join('')
return joinedArray;
}
}
};
What I'd do is:
Reduce the string to an object, where the keys are the letters and the values are objects containing counts of occurrences and initial index in the string
Sort the .values() of that object in order of minimum count and minimum index
Use the first entry in the result of the sort to return the character
So something like
function firstUnique(str) {
const counts = Array.from(str).reduce((acc, c, i) => {
(acc[c] || (acc[c] = { c, count: 0, index: i })).count++;
return acc;
}, {});
return Object.values(counts).sort((c1, c2) =>
c1.count - c2.count || c1.index - c2.index
)[0].c;
}

Write a recursive function called capitalizeFirst. Given an array of strings, capitalize the first letter of each string in the array

I see this similar algorithm was posted on stackoverflow, nevertheless I cannot understand, so I decided to post once more.
function capitalizeFirst(arr) {
if (arr.length === 1) {
return [arr[0].toUpperCase()]
}
let res = capitalizeFirst(arr.slice(0, -1))
res.push(arr.slice(arr.length - 1)[0].toUpperCase())
return res
}
console.log(capitalizeFirst(['dog', 'car', 'horse']))
Things I do not understand...
Why it is inside square brackets return [arr[0].toUpperCase()]
why not just return arr[0].toUpperCase()
Why "arr" is getting sliced twice:
here
let res = capitalizeWords(arr.slice(0,-1)
and here
res.push(arr.slice(arr.length-1)[0].toUpperCase())
Overall, I am lost, please help
I see that the OP wants to explain some found code. First, it's not very good code. The function can be restated in a couple easy to read lines.
Here's the not-so-good code annotated (comments *in stars* answer the specific OP questions)
function capitalizeWords(arr) {
// this is the degenerate case: a single item array
if (arr.length === 1) {
return [arr[0].toUpperCase()] // return a *single item array* with the one element capitalized
// incidentally, toUpperCase capitalizes all letters, not only the first, as stated in the OP title
}
// here, length must be zero or > 1. If zero, the remaining code will fail, indexing past 0
// otherwise, if length > 1, this code will run the function on the array minus
// the last element it will return an array (see above) for that last element
let res = capitalizeWords(arr.slice(0, -1))
// this says capitalize the last element.
// it's super clumsy, grabbing the last element by *slicing the array again* just before the end,
// getting that one element from the slice, and using with toUpperCase
// then pushing that uppercase result onto the result array
res.push(arr.slice(arr.length - 1)[0].toUpperCase())
return res
}
Here's a cleanup. First, isolate the capitalization logic and get that tested and correct. It will look like this:
const capitalizeWord = word => word[0].toUpperCase() + word.slice(1);
Next, realize that the most degenerate (elemental) case is capitalizing an empty array. The result of capitalizing an empty array is an empty array.
// something like
return !arr.length ? [] : // ... recursion will go here
When recursing with arrays, we generally say: "do something with the first element, and do the function with the rest of the elements". In JS, it's much more elegant to refer to the "first and rest" than to "all but the last and the last".
// first element (after we've established > 0 length)
arr[0]
// the rest of the elements
arr.slice(1)
Putting this all together...
const capitalizeWord = word => word[0].toUpperCase() + word.slice(1);
function capitalizeWords(arr) {
return arr.length ? [ capitalizeWord(arr[0]), ...capitalizeWords(arr.slice(1))] : [];
}
console.log(capitalizeWords(['dog', 'car', 'horse']))
I would forget about what that code does and concentrate on the steps you need to take to make your function work.
Recursive - so the function needs to call itself but you need to find a way to identify which element you're working on.
You need a way to break out of the recursion when you reach the end of the array.
You need a way to separate out the first letter of an element from all the rest, and update the element with a transformed string.
Here's how I might approach it.
// Pass in the array, and initialise an index
// variable
function capitalizeFirst(arr, index = 0) {
if (!arr.length) return 'Empty array';
// If we're at the end of the array
// return the array
if (index === arr.length) return arr;
// If the element is not empty
if (arr[index].length) {
// Get the first letter, and place all
// the other letters in an array called `rest`
// You can use destructuring here because strings
// are iterable
const [first, ...rest] = arr[index];
// Update the element at the current index
// with the new string making sure you join up `rest`
arr[index] = `${first.toUpperCase()}${rest.join('')}`;
}
// Call the function again increasing the index
return capitalizeFirst(arr, ++index);
}
console.log(capitalizeFirst(['dog', 'car', 'horse']));
console.log(capitalizeFirst([]));
console.log(capitalizeFirst(['dog', '', 'horse']));
console.log(capitalizeFirst(['dog', 'o', 'horse']));
Additional documentation
Destructuring assignment
Rest parameters
Template/string literals
your confusion code
1.let res = capitalizeWords(arr.slice(0,-1)
2.res.push(arr.slice(arr.length-1)[0].toUpperCase())
1.res is an variable array . when this line of code will run let res = capitalizeWords(arr.slice(0,-1)) that means first thing will be done is from your array ['dog', 'car', 'horse'] it will take out the first item that is "dog" and after capitalizeWords function will run and inside capitalizeWords function the argument passed from res is "dog" . and when the function will run if block will run because now arr has one element that is ["dog"] and that will be converted to ["DOG"] . and as like this ['car', 'horse'] this 2 elements will be converted to capital .
but it is a bit complex code to understand as a beginner.
so,you can use my simplify code . i hope you can understand this easily !!
function capitalizeWords(arr) {
if(arr.length === 1) {
return [arr[0].toUpperCase()]
}
let res = []
for (let i of arr){
res.push(i.toUpperCase())
}
return res
}
console.log(capitalizeWords(['dog', 'car', 'horse']))
your another confusion is
return [arr[0].toUpperCase()]
if you write return arr[0].toUpperCase() that means arr[0]="dog" (its a string not an array) . if you just want to print it as a string then you can write arr[0].toUpperCase() :"dog" but if you want to console it as an array then you have to write this : [arr[0].toUpperCase()] :["dog"]
Update
Added some input checking:
if (array.length < 1) return `ERROR Empty Array`;
// Return error message if input is an empty array
if (typeof str === "string" && /[a-z]/.test(str.charAt(0))) {...
/**
* Ignore all non-string data and any string that doesn't start with
* a lower case letter
*/
The code in OP doesn't capitalize each word in an array, it capitalizes every letter of each word. I honestly didn't really try to figure out what's exactly wrong because there's no recursion in the OP anyhow.
Recursion
A function that calls itself within the function (which is itself).
A base condition must be met in order for the function to call itself.
The parameters should change upon each recurse.
The function will cease calling itself once the base condition is no longer true.
In the OP, there's no base condition (see Recursion 2).
In the following example is a recursive function that capitalizes each word of an array.
Pass in the array and index (if index is undefined it defaults to 0)
function capWords(array, index = 0) {...
// array = ["dog", "cat', 'bird'], index = 0
Find the word from the array at the index
let str = array[index];
// str = 'dog'
Get the first letter of that word and capitalize it
let cap = str.charAt(0).toUpperCase();
// cap = "D"
Then concatenate cap to the rest of that word and then reassign the new word to the array at index
array[index] = cap + str.slice(1);
// array = ['Dog', 'cat', 'bird']
If index is less than the length of the array -1...
if (index < array.length - 1) {...
/**
* See Recursion 2
* index = 0, array.length -1 = 2
*/
...return and call capWords(array, index + 1)...
return capWords(array, index + 1)
/**
* See Recursion 1
* array = ['Dog', 'cat', 'bird'], index = 1
* See Recursion 3
*/
...otherwise return array
return array
/**
* See Recursion 4
* After calling capWords() recursively 2 more times, the array is
* returned one more time
* array = ["Dog", "Cat", "Bird"]
*/
function capWords(array, index = 0) {
if (array.length < 1) return `ERROR Empty Array`;
let str = array[index];
if (typeof str === "string" && /[a-z]/.test(str.charAt(0))) {
let cap = str.charAt(0).toUpperCase();
array[index] = cap + str.slice(1);
}
if (index < array.length - 1) {
return capWords(array, index + 1);
}
return array;
}
console.log(capWords(['dog', 'cat', 'bird'], 0));
console.log(capWords(['dog', '', 'bird']));
console.log(capWords([2, 'cat', 'bird'], 0));
console.log(capWords(['dog', 'cat', {}], 0));
console.log(capWords([]));
You just forgot to select the First letter charAt(0) and to add more logic to connect the first letter with the other part of the word array[0].charAt(0).toUpperCase() + array[0].slice(1).toLowerCase();
The same situation when you are recursively pushing every word into an array.
function capitalizeFirst (array){
if (array.length === 1) {
return [array[0].charAt(0).toUpperCase() + array[0].slice(1).toLowerCase()];
}
var word = capitalizeFirst(array.slice(0, -1));
word.push(array.slice(array.length-1)[0].charAt(0).toUpperCase() +
array.slice(array.length-1)[0].slice(1).toLowerCase());
return word;
}

how can i repeat a string multiple times according to its index in a string

I am trying to write a function with a string as a parameter,
and the output should be the same string with each character repeated as many times as the character's index, with capitalizing the first letter.
For example, function accum(abc) should return: A-Bb-Ccc
accum(zytx) should return: Z-Yy-Ttt-Xxxx
I tried the following code but it is not working. Can someone help me out?
function accum(s) {
var strSplit = s.toLowerCase().split('');
var newArr = strSplit.map((element, i) =>
element.repeat(i+1).charAt(0).toUpperCase()+element.substr(1));
console.log("the new Arr is: "+newArr.join('-'));
return newArr.join('-');
}
accum("abcd");
In functional style (thanks to #Redu for the comment):
const accum = (s) => Array.from(
s,
(c, i) => `${c.toLocaleUpperCase()}${c.repeat(i)}`
)
.join('-');
console.log(accum(''));
console.log(accum('a'));
console.log(accum('xyz'));
Your code doesn't work because in this line
element.repeat(i+1).charAt(0).toUpperCase()+element.substr(1))
element.substr(1) tries to get the substring starting at index 1 of a single character (which is always the empty string). You probably thought that element.repeat(i+1) would work in place (i.e. modify element) whereas it returns a new string (see MDN).
You can fix this as follows:
function accum(s) {
var strSplit = s.toLowerCase().split('');
var newArr = strSplit.map((element, i) =>
`${element.toLocaleUpperCase()}${element.repeat(i)}`);
console.log("the new Arr is: "+newArr.join('-'));
return newArr.join('-');
}
accum("abcd");
The problem is your .charAt(0) which is always taking the first character, and you're not repeating the lowercase letters afterwards.
function accum(s) {
var strSplit = s.toLowerCase().split('');
var newArr = strSplit.map(
(element, i) => element.toUpperCase()+element.repeat(i));
return newArr.join('-');
}
console.log("the new Arr is:", accum("abcd"));
console.log("zytx:", accum("zytx"));
You can simplify this even further, by removing the .substr() and just put element.repeat(i). On the first iteration, i will be 0 and return an empty string.
This can be achieved using a simple regex and repeat too, as in:
function accum(s) {
var i = 0;
return s.replace(/./g, m => "-" + m.toUpperCase() + m.repeat(i++)).slice(1);
}
console.log(accum("abcd"));
The slice(1) part is used to remove the - from the start of the string.

Check if string contains set of other string

I want to check if string one in array contain the letters from words in string 2. Here's my example array:
(["Floor", "far"]);
function should return false because "a" is not in string "Floor"
But for array like this:
(["Newbie", "web"]);
It should return true because all of letters from "web" are in "Newbie".
Here's my code so far...
function mutation(arr) {
var newArr = [];
for (i=0; i<arr.length; i++) {
newArr.push(arr[i].toLowerCase().split(""));
}
for (i=0; i<newArr.length; i++) {
for (j=0; j<newArr[i].length; j++) {
console.log(newArr[0][j]+ (newArr[1][j]));
}
}
}
mutation(["Newbie", "web"]);
I know that it won't work and I'm out of ideas how to make it. I try to make a set of all letters in two array and compare them. If there is at least one false the function should return false. Should I nest indexOf() method somewhere?
I think this should work for you. Break up the string of letters to check for into an array. Iterate over the array getting each letter and checking if the string passed in contains the letter, setting our result to false if it doesn't.
function mutation(arr) {
var charArr = arr[1].toLowerCase().split("");
var result = true;
charArr.forEach(element => {
if (!arr[0].toLowerCase().includes(element)) {
result = false;
}
});
return result;
}
console.log(mutation(["Newbie", "web"]));
The cool way would be:
const mutation =([one, two]) => (set => [...two.toLowerCase()].every(char => set.has(char)))(new Set(one.toLowerCase()));
How it works:
At first we destructure the passed array into the first and the second word:
[one, two]
Now that we got both, we build up a Set of characters from the first word:
(set => /*...*/)(new Set(one))
All that in an IIFE cause we need the set here:
[...two].every(char => set.has(char))
That spreads the second word in an array, so we got an array of chars and then checks if all characters are part of the set we built up from the other word.
If you want to be sure that one word, which might have several repeating letters, is contained in another, use Array.reduce() to count the letters, and store create a map of letter -> counts. Do that for both words. Check if all entries of 2nd word are contained in the 1st word map using Array.every():
const countLetters = (w) =>
w.toLowerCase()
.split('')
.reduce((r, l) => r.set(l, (r.get(l) || 0) + 1), new Map());
const mutation = ([a, b]) => {
const al = countLetters(a);
const bl = countLetters(b);
return [...bl].every(([k, v]) => v <= (al.get(k) || 0));
};
console.log(mutation(["Floor", "far"])); // false
console.log(mutation(["Floor", "for"])); // true
console.log(mutation(["Floor", "foroo"])); // false
console.log(mutation(["Newbie", "web"])); // true

Finding word in javascript

I have an sorted array e.g
var arr = [ "aasd","march","mazz" ,"xav" ];
And i want to find the first occurance of letter that starts with "m" here it would be 1 . Is thee any way how to do it without looping trought whole array?
You could use a binary search to find any word starting with that letter, then loop backwards until you get the first one.
Is there any way how to do it without looping trought whole array?
Yes, loop until you've found the match.
If you want to avoid a for or while construct, you can use Array's find() method.
For example, arr.find(word => word.startsWith("m")) should return the result you expect (or undefined if there's no such word).
You could use the find() function to search for the first match that meets your constraint.
The startsWith() function could easily handle this :
// Your array
var arr = [ "aasd","march","mazz" ,"xav" ];
// This will find the first match that starts with "m"
arr.find(function(word){ return word.startsWith('m');}); // yields "march"
Or if you needed a bit more extensive pattern matching, you could use a regular expression via the test() function, which can be seen in the following example and handles the same scenario (matching a string that begins with "m") :
// Your array
var arr = [ "aasd","march","mazz" ,"xav" ];
// First match that starts with "m"
var match = arr.find(function(word){ return /^m/i.test(word);}); // yields "march"
Example
var arr = ["aasd", "march", "mazz", "xav"];
var match = arr.find(function(word) { return /^m/i.test(word); });
alert(match);
You dont need to loop through the whole array - only until such time as you find what you're interested in
function findFirstIndex(arr, char){
for(var i=0;i<arr.length;i++){
if(arr[i].substring(0,1) === char)
return i;
}
return -1; // not found
}
You could use Array#some()
The some() method tests whether some element in the array passes the test implemented by the provided function.
function find(letter, array) {
var index;
array.some(function (a, i) {
if (a[0] === letter) {
index = i;
return true;
}
});
return index;
}
var arr = ["aasd", "march", "mazz", "xav"];
document.write(find('m', arr));

Categories