This topic is for those of us who are participating in the April 2018 JavaScript Algorithms and Data Structures cohort. Even though this topic is mainly for those participating in the cohort, it’s totally ok for others to participate as desired. All are welcome!
This topic covers the following sections of the fCC beta curriculum:
i’m on the Basic Data Structures: Iterate Through All an Array’s Items Using For Loops. I’m not sure why, but it looks like I have an extra array around my solution which is throwing it off.
function filteredArray(arr, elem) {
let newArr = [];
// change code below this line
for (let i = 0; i < arr.length; i++) {
if (arr[i].indexOf(elem) !== -1) {
arr.splice(i, 1);
newArr.push(arr);
}
}
// change code above this line
return newArr;
}
// change code here to test different cases:
console.log(filteredArray([[3, 2, 3], [1, 6, 3], [3, 13, 26], [19, 3, 9]], 3));
@nvrqt03 I think your logic in the code above is to determine if elem is in the subArray (arr[i]) and if it is, remove arr[i] from the original arr. When the loop finishes going through each subArray, you return what’s left in arr since all of the matching subArrays have been removed. Is this correct?
The way I thought about this one was to only add subArrays to newArr that don’t have elem in them. So, if elem is not in arr[i] then add that arr[i] to newArr. Does that make sense? I find it easier to reason through it this way as opposed to modifying the array I’m looping through and keeping track of how that works.
Here’s how I did it in case it helps to see my logic:
function filteredArray(arr, elem) {
let newArr = [];
// change code below this line
for (let indexArr = 0; indexArr < arr.length; indexArr++) {
// Create subArr variable to reuse as needed
let subArr = arr[indexArr];
// Check to see if elem is in subArr, if not, it will return -1
if (subArr.indexOf(elem) === -1) {
// Since elem is not in subArr, add subArr to newArr.
newArr.push(subArr);
}
}
// change code above this line
return newArr;
}
I’m not sure how to complete the challenge using the logic you present. If you figure it out, please share it here so I (and others) can learn from it.
@nvrqt03 I was able to pass the exercise using splice().
function filteredArray(arr, elem) {
let newArr = [];
// change code below this line
for (let i = 0; i < arr.length; i++) {
if (arr[i].indexOf(elem) !== -1) {
arr.splice(i, 1);
i--; // account for array modification
}
}
newArr = arr;
// change code above this line
return newArr;
}
// change code here to test different cases:
console.log(filteredArray([[3, 2, 3], [1, 6, 3], [3, 13, 26], [19, 3, 9]], 3));
great solutions guys! glad to see someone got splice to work. basically I was trying to say that if the element does NOT exist in the array -
if (arr[i ].indexOf(elem) !== -1
then to splice them from the array. they will make their own new array of uh… undesirables? then we will push what’s left to the newArr and return that. however I noticed @smsguy927 you didn’t push to the new array, and I’m not sure how i- - ; works in this situation.
sorry for the late reply, I code early in the morning. usually I can get some coding in after work as well, or respond during work. It was busy yesterday though.
splice() modifies the array it is called on and it shifts the indexes of the array when no elements are replaced after splicing. i-- accounts for this modification and ensures that arr[i] will point to the next element in the array in the next iteration. Then I assign what’s left in the initial array to the result array.
@nvrqt03 This will return true if elem is in arr[i].
indexOf(elem) either returns the index of the item in the array that matches elem or returns -1 if there is no match.
In the above, you’re returning true if arr[i].indexOf(elem) does not equal !== -1, i.e. return true if arr[i].indexOf(elem) returns an index of a matched item in the array, or return true if it returns anything other than -1.
The following returns true if elem is NOT in arr[i]:
if (arr[i].indexOf(elem) === -1)
That’s how I’m reading this. Let me know if I’m wrong.
if (arr[i].indexOf(elem) === -1)
if that returns true, then the element is not in the current sub-index. that is exactly what we’re looking for. so from here, you can skip all the slicing and splicing and just: newArr.push(arr[i])
for (let i = 0; i < arr.length; i++) {
if (arr[i].indexOf(elem) === -1) {
newArr.push(arr[i]);
}
}
for the first one, converting celsius to fahrenheit, I essentially got the same as you. I only let fahrenheit equal the celsius conversion, and returned fahrenheit.
reversing a string - i got your second solution.
factorialize - slightly different -
```function factorialize(num) {
if (num === 0 || num === 1)
return 1;
for (let i = num - 1; i >= 1; i–) {
num *= i;
}
return num;
}
I’ll definitely check out that recursion video!
Here are a couple others:
find the longest word in a string:
```function findLongestWordLength(str) {
let largestWord = 0;
str = str.split(’ ');
for (let i = 0; i < str.length; i++) {
if (str[i].length > largestWord) {
largestWord = str[i].length;
}
}
return largestWord;
}
return largest numbers in arrays:
```function largestOfFour(arr) {
let largestNumber = [0,0,0,0];
for (let i = 0; i < arr.length; i++) {
for (let j = 0; j < arr[i].length; j++) {
if (arr[i][j] < 0) {
arr[i].sort(function (a, b) {
return a - b;
});
largestNumber[i] = arr[i][0];
}
if (arr[i][j] > largestNumber[i])
largestNumber[i] = arr[i][j];
}
}
return largestNumber;
}
I’m working on the Confirm the Ending challenge. I think I"m close, but its inconsistent. its finding anything, not just at the end.
function confirmEnding(str, target) {
// “Never give up and good luck will find you.”
// – Falcor
if (str.lastIndexOf(target) > 0) {
return true;
}
else {
return false;
}
}
@nvrqt03 Thanks for sharing! Anyone else want to share or have comments on any of the solutions shared so far?
Here are my solutions for the next three algorithms.
Find the Longest Word in a String
For Of Loop
I like this one the best at this point in my understanding of JavaScript because it’s straightforward and there’s no unseen things happening.
function findLongestWordLength(str) {
let longest = 0;
let wordsArr = str.split(' ');
for (let word of wordsArr) {
if (word.length > longest) {
longest = word.length;
}
}
return longest;
}
Filter()
This is similar to the For Of Loop, but it uses filter() instead. I’m not sure if there are benefits to doing it this way.
function findLongestWordLength(str) {
let longest = 0;
str.split(' ').filter(word => {if (word.length > longest) longest = word.length});
return longest;
}
filter() and map()
My first attempt returned the following:
function largestOfFour(arr) {
let largestArr = [];
// Apply (i.e. map) the following filter to each sub array within the array
arr.map(function(subArr) {
let largest = 0;
/*
Filter the largest number from each sub array
if the number is greater than the previous largest number
OR the number is less than zero and the previous largest number is zero
then set largest to num
*/
subArr.filter(num => {if (num > largest || (num < 0 && largest === 0)) largest = num});
// Push the largest number of the sub array to the largestArr array
largestArr.push(largest);
});
return largestArr;
}
substr()
The Confirm the Ending fCC Guide entry suggests another (better) way to do this using substr(). Again, I need to remember to look for better, more appropriate built-in methods:
function confirmEnding(str, target) {
return str.substr(-target.length) === target;
}
Hopefully, the more I do this the more likely it’ll be that I’ll pick more appropriate methods for my solutions. What do you all think? Does anyone have solutions that aren’t shown or mentioned above?
I use map() and ES6 spread operator (the 3 dots! … )
function largestOfFour(arr) {
return arr.map(chunk => Math.max(...chunk));
// arr.map() grabs subarrays (I call it chuck here) and call the Math.max function on it to find the largest number in each subarray.
}
I found a great tool for debugging your JavaScript code. It also offers other languages like Python and Ruby.
Basically, it visualizes every single execution of the code to help you debugging.
Not only debugging, I got tons of help to understand JS functions better and faster while solving the Basic Algorithm Scripting section.
Here are my solutions for the next three algorithms:
Repeat a String Repeat a String
My first attempt looked like the following:
function repeatStringNumTimes(str, num) {
let returnStr = '';
for (let numCount=0; numCount < num; numCount++) {
if (num > 0) {
returnStr += str;
}
}
return returnStr;
}
In thinking about it further and attempting to figure out a recursive way to accomplish this, I figured this out:
function repeatStringNumTimes(str, num) {
return num <= 0 ? "" : str + repeatStringNumTimes(str, num-1);
}
The Repeat a String Repeat a String fCC guide shows a while loop solution, recursive solution, and a solution that uses the repeat() method, which the challenge says not to use. I think the while loop solution is more straightforward and easier to understand than my for loop solution above:
function repeatStringNumTimes(str, num) {
var accumulatedStr = '';
while (num > 0) {
accumulatedStr += str;
num--;
}
return accumulatedStr;
}
Truncate a String
This was what I came up with:
function truncateString(str, num) {
return str.length > num ? `${str.slice(0, num)}...` : str;
}
Interestingly, I think the Truncate a String fCC guide makes it more complicated than it has to be, at least with the current test cases. For instance, line 5 of the advanced code solution is:
return str.slice(0, num > 3 ? num - 3 : num) + '...';
If one uses the following instead, it’ll still pass all of the tests without the need to use another ternary operator:
return str.slice(0, num) + '...';
The advanced solution then becomes very similar to my solution above, except I use a template literal.
I may submit a suggested change to the guide entry if I get the time and energy.
Finders Keepers
My first attempt looked like this:
function findElement(arr, func) {
for (let num of arr) {
if (func(num)) return num;
}
}
That’s not too bad, a little awkward maybe. However, according to the Finders Keepers fCC Guide, there’s a much better way to do this using the filter() method:
function findElement(arr, func) {
filterArr = arr.filter(func);
return filterArr[0];
}
Which can be refactored even further to:
function findElement(arr, func) {
return arr.filter(func)[0];
}
Any suggestions for improvement on the above solutions?
How’s everyone doing so far? I’ve noticed that the algorithms tend to take me longer to work on and figure out, especially if I take into account the research I do after I come up with a working solution in order to make that solution better. Anyone else experiencing this?