Determine if one of the elements in an array is a string - javascript

Given an array of mixed types, "getLongestWordOfMixedElements" returns the longest string in the given array.
Notes:
If the array is empty, it should return an empty string ("").
If the array contains no strings; it should return an empty string.
How do I find out if the array contains a string or not, as in this code:
function getLongestWordOfMixedElements(arr) {
if (arr.length === 0) return ""
var max = 0
for (var i = 0; i < arr.length; i++){
if(arr[i].length > max) max = arr[i]
}
return max
}
getLongestWordOfMixedElements([3, 'word', 5, 'up', 3, 1]);

You can filter the array for strings then use a reduce operation to find the longest one
function getLongestWordOfMixedElements(arr) {
return arr
.filter(item => typeof item === 'string')
.reduce((longest, str) => str.length > longest.length ? str : longest, '');
}
console.log(getLongestWordOfMixedElements([3, 'word', 5, 'up', 3, 1]));
Note that if any words are the same length, the earlier one in the array is returned.
Additionally, you could skip the filter and do the type check in the reduce...
return arr.reduce((longest, str) => {
return typeof str === 'string' && str.length > longest.length ?
str : longest;
}, '')

Well here's my version of it...
function getLongestWordOfMixedElements(arr) {
let result = '';
if (arr.length) {
for(i in arr) {
const value = arr[i];
if (value && typeof value === 'string' && value.length > result.length) {
result = value;
}
}
}
return result;
}
getLongestWordOfMixedElements([333333, 'word', 5, 'up', 3, 1]);

You iterate over the element and check if its type is a string.
You can do so with typeof.
Let us say you would've a bunch of data and would not like to double your memory usage / or for the sake of the example in your code:
function getLongestWordOfMixedElements(arr) {
var max = "";
if (arr.length) {
arr.forEach(function (item) {
if (typeof item === "string" && item.length > max) {
max = item;
}
});
}
return max;
}
console.log(getLongestWordOfMixedElements([3, 'word', 5, 'up', 3, 1, {foo:4}]));
In your code you would change it this way:
for (var i = 0; i < arr.length; i++) {
var item = arr[i];
if (typeof item === "string" && item.length > max) {
max = arr[i];
}
}

Related

How to find the longest common prefix in an array of strings?

I'm trying to solve this using the .every method but it's not returning true and therefore it's not adding onto my string and I'm not sure why.
var longestCommonPrefix = function(arr) {
if (arr.length === 0) {
return undefined;
}
let result = '';
for (let i = 0; i < arr.length; i++) {
if (arr.every(x => arr[i].charAt(i) === x)) {
result += arr[i].charAt(i);
}
}
return result
}
console.log(longestCommonPrefix(["flower", "flow", "flight"])); //fl
You need to iterate over one string, not over the whole array: check if the first character of the string is present everywhere, then the second character, etc:
var longestCommonPrefix = function(arr) {
if (arr.length === 0) {
return undefined;
}
let result = '';
for (let i = 0; i < arr[0].length; i++) {
if (arr.every(x => x.charAt(i) === arr[0][i])) {
result += arr[i].charAt(i);
} else break;
}
return result;
}
console.log(longestCommonPrefix(["flower", "flow", "flight"])); //fl
Your use of Array.every is along the right lines. You want to check that every string in the array has the same character at position i. I think you got confused when you named the parameter x, when it is in fact a string :)
var longestCommonPrefix = function(words) {
if (words.length === 0) {
return "";
}
const letters = [];
const lengthOfShortestWord = Math.min(...words.map(word => word.length));
for (let i = 0; i < lengthOfShortestWord; i++) {
const char = words[0][i];
if (words.every(word => word[i] === char)) {
letters.push(char);
} else {
break;
}
}
return letters.join("");
}
console.log(longestCommonPrefix(["flower", "flow", "flight"])); //fl
Unless I am mistaken the longest prefix is never going to be greater than the smallest string in the array.
In this case "fl" is both the smallest string and the longest common prefix:
["flower", "fl", "flight"]
So start with finding the smallest string in arr:
let [sm] = [...arr].sort((a, b) => a.length - b.length);
Then check that all strings in arr start with sm:
arr.every(str => str.startsWith(sm));
If that isn't the case then shorten sm by one character:
sm = sm.slice(0, -1);
And keep going until you eventually find the longest prefix or sm becomes an empty string:
const prefix = arr => {
let [sm] = [...arr].sort((a, b) => a.length - b.length);
while (sm && !arr.every(str => str.startsWith(sm))) sm = sm.slice(0, -1);
return sm;
};

Find the length of the longest continuous stretch of a single number in an array

Here is the full description of the problem:
//Write a function which takes a list of numbers and returns the length of the
// longest continuous stretch of a single number. For example, on the input [1,7,7,3],
// the correct return is 2 because there are two 7's in a row. On the input
// [1,7,7,3,9,9,9,4,9], the correct return is 3, since there are three 9’s in a row.
Here is my solution:
let sequenceChecker = (arr) => {
let finalNum = 0;
let secondPass = false;
const bigestNumber = arr.sort()[arr.length - 1]
arr.forEach(num => {
if(num === bigestNumber){
finalNum++
}
else if(num != bigestNumber && finalNum > 0 ){
secondPass = true
}
else if (secondPass == true && num === bigestNumber){
finalNum = 0
}
})
return finalNum
}
console.log((sequenceChecker([1,7,7,3])).toString());
console.log((sequenceChecker([1,7,7,3,9,9,9,4,9])).toString());
I really don't understand why my code won't solve this problem. The first else if the statement never gets executed but the statement should evaluate to true and the code inside should execute.
I would do like this. Create one function that return the length of the stretch by a number, It will return -1 if the array does not include the number.
Then, I would just compare the returns for each number and return the biggest number.
const getLongestStretch = (arr, number) => {
if (!arr.includes(number)) return -1;
const filteredArrayLength = arr.filter(
(n, i) => n === number && (arr[i - 1] === number || arr[i + 1] === number)
).length;
if (filteredArrayLength === 0) return 1;
return filteredArrayLength;
};
const sequenceChecker = (arr) =>
arr.reduce(
(result, number) => Math.max(result, getLongestStretch(arr, number)),
1
);
arr = [1, 7, 7, 3, 9, 9, 9, 4, 9, 9, 9, 9, 9];
let count = 1;
let journal = new Map();
for (let i = 0; i < arr.length; i++) {
if(arr[i] == arr[i+1]) {
++count;
}else {
if(journal.get(arr[i]) < count || !journal.get(arr[i])) {
journal.set(arr[i], count);
}
count = 1;
}
}
console.log(journal) // Map(5) {1 => 1, 7 => 2, 3 => 1, 9 => 5, 4 => 1}
Try this:
i checking the number of the sequence with the previous e increment the count in a variable
var arr = [1,7,7,3,9,9,9,4,4,4,4,4,4,9,9,9,9,9,9,9];
var prev;
var count=0;
var finalnum=0;
$.each(arr, function(index,num){
if(prev != num) {
prev = num;
finalnum = (finalnum <= count ? count : finalnum);
count = 1;
}
else {
count = count + 1;
}
if(index == (arr.length - 1))
{
finalnum = (finalnum <= count ? count : finalnum);
}
});
console.log(finalnum);

How do I write a function that takes an array of values and returns an object

in this format; sample input: ["book", 1, "table", 4] sample output: { string: ["book", "table"], number: [1,4] }
here is the code i have written but it's not giving me the output i want.
function listDic(arr) {
if (Array.isArray(arr)) {
let output = {};
for (let i =0; i == arr.length; i++) {
if (typeof arr[i] === 'string') {
var str = [];
str.push(arr[i]);
}
if (typeof arr[i] === 'number') {
var num = [];
num.push(arr[i]);
}
}
return {string: str, number: num}
}
return "Only arrays are allowed.";
}
please what exactly am i getting wrong?
You could use the type directly as key for the object, while iterating the array.
If you have not an object with the key, generate a new one with an empty array for pushing the actual item.
var array = ["book", 1, "table", 4],
object = {};
array.forEach(function (a) {
var type = typeof a;
object[type] = object[type] || [];
object[type].push(a);
});
console.log(object);
You're overwriting str and num in the loop without ever keeping any other reference to the arrays. Put those arrays in the output object, and then push into those.
var data = ["book", 1, "table", 4];
console.log(listDic(data));
function listDic(arr) {
if (!Array.isArray(arr)) {
return "Only arrays are allowed.";
}
let output = {
string: [],
number: []
};
for (let i = 0; i < arr.length; i++) {
switch (typeof arr[i]) {
case "string":
output.string.push(arr[i]);
break;
case 'number':
output.number.push(arr[i]);
}
}
return output;
}
You could just reduce the array into an object, and use the type of the values as keys
var arr = ["book", 1, "table", 4];
function listDic(arr) {
return arr.reduce((a, b) => {
let t = typeof b;
a[t] ? a[t].push(b) : a[t] = [b];
return a;
}, {});
}
console.log(listDic(arr));
thanks i got a better way to solve it myself
function listDic(arr) {
if (Array.isArray(arr)) {
let str = [];
let num = [];
for (let i =0; i < arr.length; i++) {
if (typeof arr[i] === 'string') {
str.push(arr[i]);
}
if (typeof arr[i] === 'number') {
num.push(arr[i]);
}
}
return {string: str, number: num}
}
return "Only arrays are allowed.";
}
I think this should work for you :
function listDic(arr) {
if (Array.isArray(arr)) {
let output = {};
var str = [],
num = []; //CORRECTED
for (let i = 0; i < arr.length; i++) { //CORRECTED
if (typeof arr[i] === 'string') {
str.push(arr[i]);
}
if (typeof arr[i] === 'number') {
num.push(arr[i]);
}
}
return { string: str, number: num }
}
return "Only arrays are allowed.";
}
console.log(listDic(["book", 1, "table", 4]));
Explanation
Basically, there were two issues:
you were really not entering the loop with == arr.length on your for-loop's entry condition.
you kept re-assigning the str and num arrays with a re-declaration var str[i] = [] OR var num[i] = [].
Hope this helps.

Mixed Element Small Number - JS

Hi I am creating a function that returns the smallest number within the given array. If the array contains no numbers, it should return 0.
Here's my function:
function findSmallestNumberAmongMixedElements(arr){
if(arr.length === 0 && typeof arr === 'string'){
return 0;
} else{
return Math.min.apply(null, arr); //min=1
}
}
var output = findSmallestNumberAmongMixedElements([4, 'lincoln', 9, 'octopus']);
console.log(output); // --> 4
Right now my answer return NAN instead of 4. Do you have any idea what am I doing wrong?
typeof arr === "string" will always be false if you are passing an array (wether or not the array contain strings is irrelevant for that test).
What you should do is first, filter the numbers out of the array using filter, then call Math.min on the filtered array:
function findSmallestNumberAmongMixedElements(arr) {
var onlyNumbers = arr.filter(e => typeof e === "number"); // filter out only items that are numbers
if(onlyNumbers.length === 0) return 0; // if there is no numbers, return 0
return Math.min.apply(null, onlyNumbers); // otherwise return the min of them
}
var output = findSmallestNumberAmongMixedElements([4, 'lincoln', 9, 'octopus']);
console.log(output); // --> 4
Your current function may produce NaN when you try to apply Math.min to an input array which contains both string and number values. Math.min can only handle numeric inputs, so the presence of a string may cause it to return the NaN error value.
There is a simple solution: filter out all of the non-number values from the array. We can check the length of the filtered array to see if there were any non-numeric values and, if so, apply Math.min without worry.
function findSmallestNumberAmongMixedElements(arr) {
var filtered = arr.filter(function(el) {
return typeof el == 'number';
});
if (filtered.length > 0) {
return Math.min.apply(Math, filtered);
} else {
return 0;
}
}
[
[4, 'lincoln', 9, 'octopus'], // 4
[], // 0
['a', 3, 2], // 2
['h', 'i'], // 0
['-3', 3], // 3
].forEach(function(input) {
console.log(input, findSmallestNumberAmongMixedElements(input));
});
In your Math.min.apply(null, arr), you are getting NaN because there are strings in the array.
Your typeof arr === 'string' does not loop through your array to exclude string value within the array.
What you need to do to achieve your goal is to probably just do a for loop or forEach loop:
function findSmallestNumberAmongMixedElements(arr){
var min = Infinity;
// if argument is not array or array has no value
if (arr.constructor !== Array || arr.length === 0){
min = 0;
return min;
}
/* for loop */
for (var i = 0, len = arr.length; i < len; i++){
if (arr[i] === 0 || typeof arr[i] !== 'number') continue;
min = Math.min(min, arr[i]);
}
/* forEach loop */
arr.forEach(function(value, index){
if (value === 0 || typeof value !== 'number') return;
min = Math.min(min, value);
});
return min;
}
var output = findSmallestNumberAmongMixedElements([4, 'lincoln', 9, 'octopus']);
console.log(output); // --> 4
I think you should filter your array before giving it to Math.min
Try the following
function isNumber (obj) {
return obj!== undefined && typeof(obj) === 'number' && !isNaN(obj);
}
function smallestInMixedArray (arr) {
if (arr.length === 0 || !arr.filter) {
return 0;
} else {
arr = arr.filter(isNumber)
return Math.min.apply(null, arr); //min=1
}
}
var output = smallestInMixedArray([4, 'lincoln', 9, 'octopus']);
console.log(output); // --> 4

Getting Longest Word - JS

I am writing a function that returns the longest string in the given array. If the array is empty, it should return an empty string (""). If the array contains no strings; it should return an empty string.
function longestWord(arr) {
var filtered = arr.filter(function(el) { return typeof el == 'number' });
if (filtered.length > 0) {
return Math.min.apply(Math, filtered);
} else {
return 0;
}
}
var output = longestWord([3, 'word', 5, 'up', 3, 1]);
console.log(output); // --> must be 'word'
Right now my codes doesnt pull the word instead it pulls out the number. Any idea what am I missing?
Let's walk through your code.
The first line of your longestWord function:
var filtered = arr.filter(function(el) { return typeof el == 'number' });
will filter the input array based on typeof el === 'number', which will return an array containing only the elements of the input array which are type of === number.
Since the goal is to find the longest word, this should probably be changed to:
var filtered = arr.filter(function(el) { return typeof el === 'string' });
which will return an array of the strings in the input array.
Next, there's a check to see if the filtered array is empty. If the array is empty, you return 0. Your instructions say that if the array is empty, or if the array contains no strings, it should return an empty string. So we should change this to:
return "";
If the array is not empty, or contains strings, Math.min.apply(Math, filtered) is returned. This statement would return the minimum value of an array, so probably not what you want. After all, the goal is to return the longest string.
To do this we can use a variety of methods, here's one:
filtered.reduce(function(a, b) { return a.length > b.length ? a : b })
This statement uses the reduce() method to step through the array and return the longest item.
Putting it all together we get:
function longestWord(arr) {
var filtered = arr.filter(function(el) { return typeof el === 'string' });
if (filtered.length > 0) {
return filtered.reduce(function(a, b) { return a.length >= b.length ? a : b });
} else {
return "";
}
}
console.log(longestWord([3, 'word', 5, 'up', 3, 'testing', 1]));
console.log(longestWord([]));
console.log(longestWord([1, 2, 3, 4, 5]))
console.log(longestWord(['some', 'long', 'four', 'char', 'strs']))
This isn't the most efficient code. For that, seek other answers, especially those that use reduce, however I do find it more readable and thus easier to maintain:
function longestWord(arr) {
var filtered = arr.filter(el => typeof el === 'string')
.sort((a,b) => a.length > b.length ? -1 : 1 );
if (filtered.length)
return filtered[0];
return null;
}
var output = longestWord([3, 'word', 5, 'up', 3, 1]);
console.log(output); // --> must be 'word'
But what to do when two strings are the same length?
I assume the filter meant to be for "string"
Once you have the filtered array, you can simply use reduce to get the longest word
function longestWord(arr) {
return Array.isArray(arr) ?
arr
.filter(el => typeof el == 'string' )
.reduce((a,b) => b.length > a.length ? b : a) : '';
}
console.log(longestWord([3, 'word', 5, 'up', 3, 1, 'blah']));
Even shorter code
var longestWord = (arr) => Array.isArray(arr) ? arr.reduce((a,b) => (typeof b == 'string' && b.length > a.length) ? b : a, '') : '';
const longestWord = arr =>
arr.reduce((result, str) =>
typeof str == 'string' && result.length < str.length
? str
: result, '')
As all other answers are using filter(), reduce() and all that new and fancy methods, I'm gonna answer with the do-it-yourself method (i.e. the old fashion way).
function longestWord(arr) {
if ( ! ( typeof arr === 'array' ) ) {
console.log("That's not an array!");
return '';
}
var longest = ''; // By default, the longest word is the empty string
// Linear search
for ( var i = 0, length = arr.length; i < length; i++ ) {
var el = arr[i];
if ( typeof el === 'string' && el.length > longest.length ) {
// Words STRICTLY GREATER than the last found word.
// This way, only the first word (if two lengths match) will be considered.
longest = el;
}
}
return longest;
}
I know, this is probably NOT what you want since you're already using filtered(), but it works.

Categories

Resources