All Longest Strings. - javascript

I'm new to coding. I want to return all longest strings of equal length. When I run it I get:
RangeError: Maximum call stack size exceeded.
at arrayOfStrings:8:10
I know that it is looping and hitting the call limit. Is this salvageable or is there a better way? Thanks for your help!
function arrayOfStrings(allLLongestStrings) {
allLLongestStrings => {
let maxLng = Math.max(...arrayOfStrings.map( elem => elem.length))
return arrayOfStrings.filter(elem => elem.length === maxLng)
}
return arrayOfStrings();
}
arrayOfStrings(
[
'otorhinolaryngological',
'Otorhinolaryngological',
'Psychophysicotherapeutics',
'Thyroparathyroidectomized',
'Pneumoencephalographically',
'Radioimmunoelectrophoresis',
'Psychoneuroendocrinological',
'Hepaticocholangiogastrostomy',
'Spectrophotofluorometrically',
'Antidisestablishmentarianism'
]
);

I would suggest to use a different approach by reducing the array and checking if the actual string is longer than the last stored one, then take a new array with this string, otherwise check the length and if it has the same take the string for the temporary result set.
function getLongestStrings(array) {
return array.reduce((r, s, i) => {
if (!i || r[0].length < s.length) { // first or longer string
return [s];
}
if (r[0].length === s.length) { // same length
r.push(s);
}
return r;
}, []);
}
console.log(getLongestStrings(['otorhinolaryngological', 'Otorhinolaryngological', 'Psychophysicotherapeutics', 'Thyroparathyroidectomized', 'Pneumoencephalographically', 'Radioimmunoelectrophoresis', 'Psychoneuroendocrinological', 'Hepaticocholangiogastrostomy', 'Spectrophotofluorometrically', 'Antidisestablishmentarianism']));

Try sorting the array by length and then picking out the first element of the array.
function arrayOfStrings(arr) {
return arr.sort((a, b) => b.length - a.length)[0]
}
I'm sorry if you intended something else, but I couldn't understand your code so I figured
you wanted the string with the maximum length in the array.

Below is an approach I would take to get the longest strings from the array. The code comments explain the logic:
function getLongest(a) {
//Find the length of the longest word in the array
var maxLength = Math.max(...a.map(s => s.length));
//Return array after filtering words with length less than maxLength.
return a.filter(s => s.length === maxLength);
}
console.log(getLongest([
'otorhinolaryngological',
'Otorhinolaryngological',
'Psychophysicotherapeutics',
'Thyroparathyroidectomized',
'Pneumoencephalographically',
'Radioimmunoelectrophoresis',
'Psychoneuroendocrinological',
'Hepaticocholangiogastrostomy',
'Spectrophotofluorometrically',
'Antidisestablishmentarianism'
]));
This code will only work in an ES6 environment as it takes advantage of spread syntax

function allLongestStrings(inputArray) {
const s = inputArray
const m = inputArray.map((e) => {
return e.length
}).sort((a, b) => b - a)[0]
return s.filter((b) => {
if ( b.length === m ) return b
})
}

I solved it like this:
function longest(array) {
let longitud = array.length;
const arreglo = [];
maximaLongitud = array.sort((a,b) => b.length - a.length)[0].length
console.log(maximaLongitud)
for (let i = 0; i < longitud; i++) {
if (array[i].length === maximaLongitud) {
arreglo.push(array[i]);
}
}
return arreglo;
}

Related

How do I compare two arrays for different message outcomes?

I am trying to compare two arrays( containing 3 integers) and return a hint message array that conform to the logic
-Push “Almost” when 1 digit and position match in array
-push “not quite” when 1 digit matches but different position
-push “incorrect “ when no digits match
push “correct” When exact match
Example of arrays :
Array1 = [2,7,6]
ReferenceArray= [2,9,7]
Hint= [“Almost”, “Not Quite”];
Code I have so far:
function check( array1, referenceArray ) {
let hint=[];
for(i=0;i<referenceArray.length;i++){
for (j=0;j<Array1.length;j++){
//value and position match
if ((referenceArray[i] && reference.indexOf[i]) === (Array1[j] && Array1.indexOf[j])) {
return hint.push('almost');
}
//value matches but not position
else if(( referenceArray[i] ===Array1[j]) && !(referenceArray.indexOf[i]===Array1.indexOf[j] )){
return hint.push('not quite');
}
}// end of Array1 iteration
} // end of reference interation
// if all values and position match
if(referenceArray===Array1){
return hint.push("correct");
}
//if no values match
else if (referenceArray!==Array1){
return hintArray.push("incorrect");
}
I would use some built in Array methods to help achieve this: every(), map() and findIndex().
I generally avoid using .push() because it mutates the array. Immutable code is nice to read 😉
const check = (array, referenceArray) => {
if (array.every((val, index) => val === referenceArray[index] )) {
return ['Correct']
}
const allHints = array.map((val, index) => {
const refArrayIndex = referenceArray.findIndex(refVal => val === refVal);
if (refArrayIndex === index) {
return 'Almost'
}
if (refArrayIndex !== -1) {
return 'Not Quite'
}
return undefined
});
const hints = allHints.filter((hint) => hint !== undefined);
if (hints.length > 0) {
return hints;
}
return ['Incorrect']
};
const hints = check([2,7,6],[2,9,7]);
console.log('hints', hints)
I did this code, tell me if it works or not 😁
const array1 = [2,7,6]
const ReferenceArray = [2,9,7]
function compareArrays(arr){
let perfect = true
for(let i = 0; i < ReferenceArray.length; i++){
if(ReferenceArray[i] != arr[i]) {
perfect = false
break
}
}
if(perfect) return 'correct'
let hint = []
for(let i = 0; i < ReferenceArray.length; i++){
if(arr[i] == ReferenceArray[i]) hint.push('Almost')
else if(ReferenceArray.includes(arr[i])) hint.push('Not Quite')
}
if(hint.length > 0) return hint
return 'incorrect'
}
console.log(compareArrays(array1))

Find Missing Character in a Character Array (javascript)

I am trying to write a function that takes in an array of individual characters (eg.['a','b','d']) and returns the first character that is missing (eg. 'c'). I am not sure why my current function doesn't work as described.
const alph = "abcdefghijklmnopqrstuvwxyz";
const findMissingLetter = (arr) => {
arr.forEach((l, i, a) => {
const ltrIdx = alph.indexOf(l); //a's index in the alph is 0
const arrNxtLtr = a[i+1]; //the next ltr after a is c
if(arrNxtLtr !== alph[ltrIdx + 1]) return alph[ltrIdx + 1] //return the letter that is missing from the arr
})
return -1 //return -1 if there is no missing char
}
console.log(findMissingLetter(['a','c']))
ps. I've seen similar approaches to solve this general problem, I am just simply wondering what I've done wrong with my function so I can learn.
Thank you!
If you simply want to find the first mismatch between two strings, then just compare them character by character until you find a mismatch or reach the end of the input string:
const alph = "abcdefghijklmnopqrstuvwxyz";
const findMissingLetter = (arr) => {
for(let i=0; i<arr.length; i++) {
if(arr[i] !== alph[i]) {
return alph[i]; // found the first mismatch
}
}
return -1 // return -1 if there is no missing char
}
console.log(findMissingLetter([]),"-1?");
console.log(findMissingLetter(['a']),"-1?");
console.log(findMissingLetter(['b']),"a?");
console.log(findMissingLetter(['a','b']),"-1?");
console.log(findMissingLetter(['a','c']),"b?");
And avoid forEach() if you want to return from inside a loop as it was commented already.
And if the input string does not have to start at the beginning of the "big" string, locate it's first character and do the comparison from there:
const alph = "abcdefghijklmnopqrstuvwxyz";
const findMissingLetter = (arr) => {
if(arr.length===0)
return -1;
let start = alph.indexOf(arr[0]);
for(let i=0; i<arr.length; i++) {
if(arr[i] !== alph[start+i]) {
return alph[start+i]; // found the first mismatch
}
}
return -1 // return -1 if there is no missing char
}
console.log(findMissingLetter([]),"-1?");
console.log(findMissingLetter(['a']),"-1?");
console.log(findMissingLetter(['b']),"-1?");
console.log(findMissingLetter(['a','b']),"-1?");
console.log(findMissingLetter(['a','c']),"b?");
console.log(findMissingLetter(['b','c','e','f']),"d?");
The reason is that forEach ignores return or any shortcircuit statement. You must instead of trying return the value from the foreach, just save it into another variable and return that variable after the forEach is done.
const alph = "abcdefghijklmnopqrstuvwxyz";
const findMissingLetter = (arr) => {
let missingLetter
arr.forEach((letter, index) => {
if(letter !== alph[index]) missingLetter ??= alph[index]
else missingLetter = -1
})
return missingLetter
}
console.log(findMissingLetter(['a','c']))

This question is about an exercise in the book Eloquent JavaScript

The last part to this exercise is to write a recursive function that takes two parameters, a joined list and an index respectively. The function will find the value in the object within the list at it's respective index. The code i have written works the way i want (i can see it working when i console.log for every occasion the function is called. But on the last occasion it refers undefined as my value. I cannot understand why. Oh and it works for index of 0. code as followed.
and first, list looks like this:
list = {
value: 1,
rest: {
value: 2,
rest: {
value: 3,
rest: null
}
}
};
const nth = (list, targetNum) => {
let value = Object.values(list)[0];
if (targetNum == 0) {
return value;
} else {
targetNum = targetNum -1;
list = Object.values(list)[1];
// console.log(value);
// console.log(targetNum);
// console.log(list);
nth(list, targetNum);
}
};
console.log(nth(arrayToList([1,2,3]),2));
below is the code for arrayToList it was the first part of the exercise and if you have any comments that's cool, cause the hints ended up suggesting to build the list from the end.
const arrayToList = (arr) => {
let list = {
value: arr[0],
rest: nestObject()
};
function nestObject() {
let rest = {};
arr.shift();
const length = arr.length;
if (length == 1) {
rest.value = arr[0];
rest.rest = null;
} else {
rest.value = arr[0];
rest.rest = nestObject();
}
return rest;
}
return list;
};
Both solutions are convoluted and unnecessary verbose. Actually, both functions could be one-liners. Here are a few hints:
For the toList thing consider the following:
if the input array is empty, return null (base case)
otherwise, split the input array into the "head" (=the first element) and "tail" (=the rest). For example, [1,2,3,4] => 1 and [2,3,4]
return an object with value equal to "head" and rest equal to toList applied to the "tail" (recursion)
On a more advanced note, the split can be done right in the function signature with destructuring:
const toList = ([head=null, ...tail]) => ...
Similarly for nth(list, N)
if N is zero, return list.value (base case)
otherwise, return an application of nth with arguments list.rest and N-1 (recursion)
Again, the signature can benefit from destructuring:
const nth = ({value, rest}, n) =>
Full code, if you're interested:
const toList = ([value = null, ...rest]) =>
value === null
? null
: {value, rest: toList(rest)}
const nth = ({value, rest}, n) =>
n === 0
? value
: nth(rest, n - 1)
//
let lst = toList(['a', 'b', 'c', 'd', 'e', 'f'])
// or simply toList('abcdef')
console.log(lst)
console.log(nth(lst, 0))
console.log(nth(lst, 4))
You simply need to add a return when recursively calling nth. Otherwise the logic is carried out but no value is returned (unless targetNum is 0)
const nth = (list, targetNum) => {
let value = Object.values(list)[0];
if (targetNum == 0) {
return value;
} else {
targetNum = targetNum -1;
list = Object.values(list)[1];
return nth(list, targetNum); // return needed here too
}
};
Or more succinctly:
const nth = (list, n) => n === 0 ? list.value : nth(list.rest, n - 1)
Here's another non-recursive arrayToList that builds the list from the end:
const arrayToList = arr => arr.slice().reverse().reduce((rest, value) => ({value, rest}), null);
(The slice here is just to make a copy of the array so that the original is not reversed in place.)
Georg’s recursive solutions are beautiful!
I’d like to add the hinted “build the list from the end” solution from the book:
const arrayToList => (arr) => {
var list
while (arr.length) {
list = {value: arr.pop(), rest: list}
}
return list
}

reduce method in javascript gets undefined

How do I use the reduce method in solving this problem? I keep getting undefined. I am trying to only print out the numbers that are bigger while going through the loop. so for example [ 1,4,2,9,1,12] will give me the printout of 1,4,9,12- here is what I got... and I keep getting undefined for the accumulator????
**
function main(array){
let myNum;
let answer=[];
outPut = array.reduce((accumulator, element) => {
const num = accumulator;
myNum= num > element? answer.push(num):
answer.push(element);
}, 0);
console.log(outPut);
}**
main([20, 3, 22, 15, 6, 1]);
You need to return the accumulator in reduce().
A simpler version is to check the index is zero or value is greater than previous in the accumulator to determine whether to add current value or not
const data = [ 1,4,2,9,1,2,12];
const res = data.reduce((a, c, i) => {
return (!i || c > a[a.length-1]) ? a.concat(c) : a;
},[])
console.log(res)
If you want [1,4,2,9,1,12] to return [1,4,9,12], array.reduce isn't the way to go.
Try
function sortArray(array) {
const sortedArray = array
.sort((a, b) => a - b) //sort by ascending
.filter((e, index) => array.indexOf(e) == index) //remove duplicates
console.log(sortedArray);
}
That's because the reduce() works with callback which return nunber. You are not returning anything.
But the main issue is the fact you are pushing items into answer. But then you are trying to log outPut, which is not initialized and the only value it could have is from wrongly used reduce().
Try this:
function main(array){
let myNum;
let answer=[];
array.reduce((accumulator, element) => {
const num = accumulator;
let biggerOne;
if(num > element) {
biggerOne = num;
} else {
biggerOne = element;
}
answer.push(biggerOne);
return biggerOne;
}, 0);
console.log(answer);
}**
main([20, 3, 22, 15, 6, 1]);

in the easiest and most concise way as possible

I want to sort an array values in an ascending or descending order without using sort().
I have created a function, however I am not satisfied with it.
I believe the code below could be much shorter and more concise.
Please let me know where to modify or you may entirely change the code too. Thank you in advance.
const func = arg => {
let flip = false;
let copy = [];
for(let val of arg) copy[copy.length] = val;
for(let i=0; i<arg.length; i++) {
const previous = arg[i-1];
const current = arg[i];
if(previous > current) {
flip = true;
copy[i] = previous;
copy[i-1] = current;
}
}
if(flip) return func(copy);
return copy;
};
l(func([5,2,8,1,9,4,7,3,6]));
If your input is composed of whole numbers, as in the example, pne option is to reduce the array into an object, whose keys are the numbers, and whose values are the number of times those values have occured so far. Then, iterate over the object (whose Object.entries will iterate in ascending numeric key order, for whole number keys), and create the array to return:
const func = arr => {
const valuesObj = {};
arr.forEach((num) => {
valuesObj[num] = (valuesObj[num] || 0) + 1;
});
return Object.entries(valuesObj)
.flatMap(
([num, count]) => Array(count).fill(num)
);
};
console.log(
func([5,2,8,1,9,10,10,11,4,7,3,6])
);
This runs in O(N) time.
To account for negative integers as well while keeping O(N) runtime, create another object for negatives:
const func = arr => {
const valuesObj = {};
const negativeValuesObj = {};
arr.forEach((num) => {
if (num >= 0) valuesObj[num] = (valuesObj[num] || 0) + 1;
else negativeValuesObj[-num] = (negativeValuesObj[-num] || 0) + 1;
});
return [
...Object.entries(negativeValuesObj).reverse()
.flatMap(
([num, count]) => Array(count).fill(-num)
),
...Object.entries(valuesObj)
.flatMap(
([num, count]) => Array(count).fill(num)
)
];
};
console.log(
func([5,2,8,1,-5, -1, 9,10,10,11,4,7,3,6, -10])
);
For non-integer items, you'll have to use a different algorithm with higher computational complexity.

Categories

Resources