Here is one to get your brain going! I've not had any luck with it.
[1,2,1,1,2,1,1,1,2,2]
[1,2,1,1,2,1]
I would like to use the second array to find the values in the first, but they must be in the same order.
Once for I would like it to return the next key up from the last key in the second array.
So in this example it would use the first six digits in the first array and then return 6 as the key after the final one in the second array.
var a2 = [1,2,1,1,2,1,1,1,2,2]
var a1 = [1,2,1,1,0,1]
function find(arr1, arr2) {
var len = 1
var result = 0;
var s2 = arr2.toString();
for (len=1;len <= a1.length; len++)
{
var aa1 = arr1.slice(0, len)
var s1 = aa1.toString();
if(s2.indexOf(s1)>=0){
result = aa1.length;
}
else {
break;
}
}
return result;
}
alert(find(a1, a2));
var find = function(haystack, needle) {
var doesMatch = function(offset) {
for (var i = 0; i < needle.length; i++) {
if (haystack[i+offset] !== needle[i]) {
return false;
}
}
return true;
};
for (var j=0; j < haystack.length - needle.length; j++) {
if (doesMatch(j)) {
return j;
}
}
return -1;
};
This is quick, this is dirty, and this is correct only if your data doesn't include any comma.
var needle = [1,2,1,1,2,1];
var haystack = [1,2,1,1,2,1,1,1,2,2];
if ( needle.length <= 0 ) return 0;
var fromStr = ','+haystack.toString()+','
var findStr = ','+needle.toString()+','
// Find ',1,2,1,1,2,1,' in ',1,2,1,1,2,1,1,1,2,2,'
var pos = fromStr.indexOf(findStr);
// Count the end position requested
return pos >= 0 ? fromStr.slice(0,pos+1).match(/,/g).length + needle.length - 1 : -1;
Note: The comma at head and tail is to make sure [22,12] doesn't match [2,1].
Related
I am trying to do one problem of hackerrank but I am not able to solve that problem
Can someone please help me with wrong logic implementation done by me?
problem
Print the length of the longest string, such that is a child of both s1 and s2.
Sample Input
HARRY
SALLY
Sample Output
2
Explanation
The longest string that can be formed by deleting zero or more characters from HARRY and SALLY is AY, whose length is 2.
Sample Input 1
AA
BB
Sample Output 1
0
Explanation 1
AA and BB have no characters in common and hence the output is 0
Sample Input 2
SHINCHAN
NOHARAAA
Sample Output 2
3
Explanation 2
The longest string that can be formed between SHINCHAN and NOHARAAA while maintaining the order is NHA.
I have written some logic which is as follows:
function commonChild(s1, s2) {
var arr = s2.split(),
currenString = '',
maxLength = 0,
index = -1;
console.log(arr);
for (var i = 0; i < s1.length; i++) {
var char = s1.charAt(i),
charIndex = arr.indexOf(char);
console.log(char)
if (index < charIndex) {
index = charIndex;
currenString +=char;
}
maxLength= Math.max(maxLength,currenString.length)
}
return maxLength;
}
commonChild('ABCDEF', 'FBDAMN');
console.log(commonChild('ABCDEF', 'FBDAMN'));
pardon me. this is an unoptimized solution.
function maxCommon(a, b, offset) {
offset = offset || 0;
if (a === b) {
return [[a, b]];
}
var possibleSolns = [];
for (var i = 0 + offset; i < a.length; i++) {
for (var j = 0 + offset; j < b.length; j++) {
if (a.charAt(i) === b.charAt(j)) {
possibleSolns.push([
a.substring(0, offset) + a.substring(i),
b.substring(0, offset) +b.substring(j)
]);
break;
}
}
}
var results = [];
possibleSolns.forEach(function(soln) {
var s = maxCommon(soln[0], soln[1], offset+1);
if (s.length === 0) {
s = [[soln[0].substring(0, offset +1), soln[1].substring(0, offset +1)]];
}
results = results.concat(s);
});
return results;
}
var maxLen = -1;
var soln = null;
maxCommon("ABCDEF", "FBDAMN").map(function(_) {
return _[0];
}).forEach(function(_) {
if (_.length > maxLen) {
soln = _;
maxLen = _.length;
}
});
console.log(soln);
I kept most of your logic in the answer:
function commonChild(s1, s2) {
var // Sets strings to arrays
arrayString1 = s1.split(""),
arrayString2 = s2.split(""),
collectedChars = "",
maxLength = 0,
max = arrayString1.length;
for (var i = 0; i < max; i++) {
var
char = arrayString1[i],
count = arrayString2.indexOf(char);
// check if char is in second string and not in collected
if (count != -1 && collectedChars.indexOf(char) == -1) {
collectedChars += char;
maxLength++;
}
}
return maxLength;
}
// expected output 4
console.log(commonChild(
'ABCDEF',
'FBDAMN'
));
// expected output 1
console.log(commonChild(
'AA',
'FBDAMN'
));
Using lodash and spread operation you can do it in this way.
const test = (first, second) => {
const stringArray1 = [...first];
const stringArray2 = [...second];
return _.intersection(stringArray1, stringArray2).length;
}
console.log(test('ABCDEF', 'FBDAMN'));
You can solve it using lcs least common subsequence
function LCS(s1,s2,x,y){
var result = 0;
if(x==0 || y==0){
result = 0
}else if(s1[x-1] == s2[y-1]){
result = 1+ LCS(s1,s2,x-1,y-1)
} else if(s1[x-1] != s2[y-1]){
result = Math.max(LCS(s1,s2,x-1,y), LCS(s1,s2,x,y-1))
}
return result;
}
// Complete the commonChild function below.
function commonChild(s1, s2) {
return LCS(s1,s2,s1.length,s2.length);
}
Based on your code before the edit.
One little change is to change var arr = s2.split() to split('').
The main change in the logic is that I added a loop to run over the string each time from another character (first loop from the first, second from the second etc).
function commonChild(s1, s2) {
var arr = s2.split(''),
currenString = '',
maxLength = 0,
index = -1,
j = -1;
for (var ii = 0; ii < s1.length; ii++) {
index = -1;
currenString = '';
for (var i = ii; i < s1.length; i++) {
var char = s1.charAt(i),
j = arr.indexOf(char);
if (index < j) {
index = j;
currenString += char;
}
maxLength = Math.max(maxLength, currenString.length)
}
}
return maxLength;
}
console.log(commonChild('ABCDEF', 'FBDAMN'));
I am trying to solve a task on the leetcode site. My approach to solving this problem was to iterate over a string, and then fill first one array until I find a repeating character, and then start filling another array, until I find a repeating character there as well. Once I would have two filled arrays, I would compare them and keep the longer one, until I am done with iteration. But with these approach I end up checking a lot of things and not sure what to do when I have the secondArray filled and I am still doing the subiteration, to avoid filling the firstArray as well.
In general this code is to cumbersome, and I am not sure anymore how should I solve this?
s = "anviaj"
s = "eeydgwdykpv"
var lengthOfLongestSubstring = function(s) {
let firstArray = [];
let secondArray = [];
let firstArrayFull = false;
let secondArrayFull = false;
let subIterationFinished = false;
if (s.length == 1)
return s;
for (var i = 0; i < s.length -1; i++) {
if (!firstArrayFull) {
firstArray.push(s.charAt(i));
} else if (!secondArrayFull) { secondArray.push(s.charAt(i)); }
for (let j = i + 1; j < s.length; j++) {
if (j + 1 == s.length) {
subIterationFinished = true;
checkArrays();
}
if (!firstArrayFull && !firstArray.includes(s.charAt(j))) {
if (secondArrayFull && !subIterationFinished) {
firstArray = firstArray;
} else {
firstArray.push(s.charAt(j));
}
} else {
firstArrayFull = true;
if (secondArrayFull) {
checkArrays();
}
}
if (firstArrayFull && secondArray.length != 0 && secondArray.includes(s.charAt(j))) {
secondArrayFull = true;
checkArrays();
}
if (firstArrayFull && secondArray.length != 0 && !secondArray.includes(s.charAt(j))) {
secondArray.push(s.charAt(j));
}
}
}
function checkArrays() {
if (secondArray.length > firstArray.length) {
firstArray = [];
firstArrayFull = false;
secondArrayFull = true;
} else {
secondArray = [];
secondArrayFull = false;
firstArrayFull = true;
}
}
return secondArray.length > firstArray.length ? secondArray : firstArray;
};
console.log(lengthOfLongestSubstring(s));
This is a valid, O(n) solution which only constructs the final string once, tested against a 20.000 length string (it should be still fast with a million characters, but stackoverflow limits input to 30K characters).
/**
* #param {string} s
* #return {number}
*/
var lengthOfLongestSubstring = function(s) {
var l = 0;
var r = 0;
var maxL = 0;
var maxR = 0;
var length = () => r - l;
var maxLength = () => maxR - maxL;
var keys = {};
while (r < s.length) {
if (s[r] in keys) {
var newL = keys[s[r]] + 1;
for (var i = l; i < newL; i++) {
delete keys[s[i]];
}
if (maxLength() < length()) {
maxL = l;
maxR = r;
}
l = newL;
}
keys[s[r]] = r;
r = r + 1;
}
if (maxLength() < length()) {
maxL = l;
maxR = r;
}
return maxLength();
};
console.log(lengthOfLongestSubstring("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"))
Use two variable, one to keep track of the longest substring and the other to keep track of current longest substring without repetition.
Iterate through your string.
Check if the current word contains the current character.
If it contains, then checks the length of current word with the longest substring. If it is greater, the update the longest substring.
Update the current word from the last seen index till the length of the current word.
Continue till end of your input string.
var lengthOfLongestSubstring = function(s) {
var longestSubstring = '';
var currentWord = '';
for(var i = 0 ; i < s.length ; i++){
var foundIndex = currentWord.indexOf(s[i]);
if(foundIndex > -1){
if(longestSubstring.length < currentWord.length)
longestSubstring = currentWord;
currentWord = currentWord.slice(foundIndex+1);
}
currentWord += s[i];
}
return longestSubstring.length < currentWord.length ? currentWord.length : longestSubstring.length;
};
console.log(lengthOfLongestSubstring("bbbbb"));
console.log(lengthOfLongestSubstring("abcdaajkljl"));
console.log(lengthOfLongestSubstring("pwwkew"));
console.log(lengthOfLongestSubstring("ysbghjjrfumqjpyktddsnxftvdqgxzlvrneaynufhgyqxwaqzelmbsiyxaubrqvguvehpmrykhvikkqzwttg"));
well this is challenging but i figure it out
here is an O(n) solution. cant do better then this
function lengthOfLongestSubstring(str) {
var currentLength = 0;
var result = 0;
var keys = {};
for (var i in str) {
if (keys[str[i]] === true) {
currentLength = 0;
keys = {};
}
keys[str[i]] = true;
currentLength++;
if (currentLength > result) {
result = currentLength;
}
}
return result
}
console.log(lengthOfLongestSubstring("bbbbb"));
console.log(lengthOfLongestSubstring("abcdaajkljl"));
console.log(lengthOfLongestSubstring("pwwkew"));
console.log(lengthOfLongestSubstring("ysbghjjrfumqjpyktddsnxftvdqgxzlvrneaynufhgyqxwaqzelmbsiyxaubrqvguvehpmrykhvikkqzwttg"));
Can use String#includes() to check if your substring has duplicates
s = "anviaj"
s1 = "eeydgwdykpv"
function findLongest(str) {
// reduce() iterates array created from split input and returns longest sub string
return str.split('').reduce((a,c,i)=>{
// start our substring using first character of str
let sub = str[0], j = 0;
// sub.includes(char) returns true if char already in sub string
while (++j < str.length && !sub.includes(str[j])) {
// no duplicate so add char to substring
sub += str[j];
}
// remove first character from input string each iteration
str = str.slice(1);
// replace current longest if applicable
return sub.length > a.length ? sub : a;
},'');
}
console.log(findLongest(s))
console.log(findLongest(s1))
I was wondering if there is a way to check for repeated characters in a string without using double loop. Can this be done with recursion?
An example of the code using double loop (return true or false based on if there are repeated characters in a string):
var charRepeats = function(str) {
for(var i = 0; i <= str.length; i++) {
for(var j = i+1; j <= str.length; j++) {
if(str[j] == str[i]) {
return false;
}
}
}
return true;
}
Many thanks in advance!
This will do:
function hasRepeats (str) {
return /(.).*\1/.test(str);
}
(A recursive solution can be found at the end of this answer)
You could simply use the builtin javascript Array functions some MDN some reference
var text = "test".split("");
text.some(function(v,i,a){
return a.lastIndexOf(v)!=i;
});
callback parameters:
v ... current value of the iteration
i ... current index of the iteration
a ... array being iterated
.split("") create an array from a string
.some(function(v,i,a){ ... }) goes through an array until the function returns true, and ends than right away. (it doesn't loop through the whole array, which is good for performance)
Details to the some function here in the documentation
Here some tests, with several different strings:
var texts = ["test", "rest", "why", "puss"];
for(var idx in texts){
var text = texts[idx].split("");
document.write(text + " -> " + text.some(function(v,i,a){return a.lastIndexOf(v)!=i;}) +"<br/>");
}
//tested on win7 in chrome 46+
If you will want recursion.
Update for recursion:
//recursive function
function checkString(text,index){
if((text.length - index)==0 ){ //stop condition
return false;
}else{
return checkString(text,index + 1)
|| text.substr(0, index).indexOf(text[index])!=-1;
}
}
// example Data to test
var texts = ["test", "rest", "why", "puss"];
for(var idx in texts){
var txt = texts[idx];
document.write( txt + " ->" + checkString(txt,0) + "<br/>");
}
//tested on win7 in chrome 46+
you can use .indexOf() and .lastIndexOf() to determine if an index is repeated. Meaning, if the first occurrence of the character is also the last occurrence, then you know it doesn't repeat. If not true, then it does repeat.
var example = 'hello';
var charRepeats = function(str) {
for (var i=0; i<str.length; i++) {
if ( str.indexOf(str[i]) !== str.lastIndexOf(str[i]) ) {
return false; // repeats
}
}
return true;
}
console.log( charRepeats(example) ); // 'false', because when it hits 'l', the indexOf and lastIndexOf are not the same.
function chkRepeat(word) {
var wordLower = word.toLowerCase();
var wordSet = new Set(wordLower);
var lenWord = wordLower.length;
var lenWordSet =wordSet.size;
if (lenWord === lenWordSet) {
return "false"
} else {
return'true'
}
}
Using regex to solve=>
function isIsogram(str){
return !/(\w).*\1/i.test(str);
}
console.log(isIsogram("isogram"), true );
console.log(isIsogram("aba"), false, "same chars may not be adjacent" );
console.log(isIsogram("moOse"), false, "same chars may not be same case" );
console.log(isIsogram("isIsogram"), false );
console.log(isIsogram(""), true, "an empty string is a valid isogram" );
The algorithm presented has a complexity of (1 + n - (1)) + (1 + n - (2)) + (1 + n - (3)) + ... + (1 + n - (n-1)) = (n-1)*(1 + n) - (n)(n-1)/2 = (n^2 + n - 2)/2 which is O(n2).
So it would be better to use an object to map and remember the characters to check for uniqueness or duplicates. Assuming a maximum data size for each character, this process will be an O(n) algorithm.
function charUnique(s) {
var r = {}, i, x;
for (i=0; i<s.length; i++) {
x = s[i];
if (r[x])
return false;
r[x] = true;
}
return true;
}
On a tiny test case, the function indeed runs a few times faster.
Note that JavaScript strings are defined as sequences of 16-bit unsigned integer values. http://bclary.com/2004/11/07/#a-4.3.16
Hence, we can still implement the same basic algorithm but using a much quicker array lookup rather than an object lookup. The result is approximately 100 times faster now.
var charRepeats = function(str) {
for (var i = 0; i <= str.length; i++) {
for (var j = i + 1; j <= str.length; j++) {
if (str[j] == str[i]) {
return false;
}
}
}
return true;
}
function charUnique(s) {
var r = {},
i, x;
for (i = 0; i < s.length; i++) {
x = s[i];
if (r[x])
return false;
r[x] = true;
}
return true;
}
function charUnique2(s) {
var r = {},
i, x;
for (i = s.length - 1; i > -1; i--) {
x = s[i];
if (r[x])
return false;
r[x] = true;
}
return true;
}
function charCodeUnique(s) {
var r = [],
i, x;
for (i = s.length - 1; i > -1; i--) {
x = s.charCodeAt(i);
if (r[x])
return false;
r[x] = true;
}
return true;
}
function regExpWay(s) {
return /(.).*\1/.test(s);
}
function timer(f) {
var i;
var t0;
var string = [];
for (i = 32; i < 127; i++)
string[string.length] = String.fromCharCode(i);
string = string.join('');
t0 = new Date();
for (i = 0; i < 10000; i++)
f(string);
return (new Date()) - t0;
}
document.write('O(n^2) = ',
timer(charRepeats), ';<br>O(n) = ',
timer(charUnique), ';<br>optimized O(n) = ',
timer(charUnique2), ';<br>more optimized O(n) = ',
timer(charCodeUnique), ';<br>regular expression way = ',
timer(regExpWay));
let myString = "Haammmzzzaaa";
myString = myString
.split("")
.filter((item, index, array) => array.indexOf(item) === index)
.join("");
console.log(myString); // "Hamza"
Another way of doing it using lodash
var _ = require("lodash");
var inputString = "HelLoo world!"
var checkRepeatition = function(inputString) {
let unique = _.uniq(inputString).join('');
if(inputString.length !== unique.length) {
return true; //duplicate characters present!
}
return false;
};
console.log(checkRepeatition(inputString.toLowerCase()));
const str = "afewreociwddwjej";
const repeatedChar=(str)=>{
const result = [];
const strArr = str.toLowerCase().split("").sort().join("").match(/(.)\1+/g);
if (strArr != null) {
strArr.forEach((elem) => {
result.push(elem[0]);
});
}
return result;
}
console.log(...repeatedChar(str));
You can also use the following code to find the repeated character in a string
//Finds character which are repeating in a string
var sample = "success";
function repeatFinder(str) {
let repeat="";
for (let i = 0; i < str.length; i++) {
for (let j = i + 1; j < str.length; j++) {
if (str.charAt(i) == str.charAt(j) && repeat.indexOf(str.charAt(j)) == -1) {
repeat += str.charAt(i);
}
}
}
return repeat;
}
console.log(repeatFinder(sample)); //output: sc
const checkRepeats = (str: string) => {
const arr = str.split('')
const obj: any = {}
for (let i = 0; i < arr.length; i++) {
if (obj[arr[i]]) {
return true
}
obj[arr[i]] = true
}
return false
}
console.log(checkRepeats('abcdea'))
function repeat(str){
let h =new Set()
for(let i=0;i<str.length-1;i++){
let a=str[i]
if(h.has(a)){
console.log(a)
}else{
h.add(a)
}
}
return 0
}
let str = '
function repeat(str){
let h =new Set()
for(let i=0;i<str.length-1;i++){
let a=str[i]
if(h.has(a)){
console.log(a)
}else{
h.add(a)
}
}
return 0
}
let str = 'haiiiiiiiiii'
console.log(repeat(str))
'
console.log(repeat(str))
Cleanest way for me:
Convert the string to an array
Make a set from the array
Compare the length of the set and the array
Example function:
function checkDuplicates(str) {
const strArray = str.split('');
if (strArray.length !== new Set(strArray).size) {
return true;
}
return false;
}
You can use "Set object"!
The Set object lets you store unique values of any type, whether
primitive values or object references. It has some methods to add or to check if a property exist in the object.
Read more about Sets at MDN
Here how i use it:
function isIsogram(str){
let obj = new Set();
for(let i = 0; i < str.length; i++){
if(obj.has(str[i])){
return false
}else{
obj.add(str[i])
}
}
return true
}
isIsogram("Dermatoglyphics") // true
isIsogram("aba")// false
I am trying to count the number of permutations that do not contain consecutive letters. My code passes tests like 'aabb' (answer:8) and 'aab' (answer:2), but does not pass cases like 'abcdefa'(my answer: 2520; correct answer: 3600). Here's my code:
function permAlone(str) {
var totalPerm = 1;
var result = [];
//assign the first letter
for (var i = 0; i < str.length; i++) {
var firstNum = str[i];
var perm = firstNum;
//create an array from the remaining letters in the string
for (var k = 0; k < str.length; k++) {
if (k !== i) {
perm += str[k];
}
}
//Permutations: get the last letter and change its position by -1;
//Keep changing that letters's position by -1 until its index is 1;
//Then, take the last letter again and do the same thing;
//Keep doing the same thing until the total num of permutations of the number of items in the string -1 is reached (factorial of the number of items in the string -1 because we already established what the very first letter must be).
var permArr = perm.split("");
var j = permArr.length - 1;
var patternsLeft = totalNumPatterns(perm.length - 1);
while (patternsLeft > 0) {
var to = j - 1;
var subRes = permArr.move(j, to);
console.log(subRes);
if (noDoubleLettersPresent(subRes)) {
result.push([subRes]);
}
j -= 1;
if (j == 1) {
j = perm.length - 1;
}
patternsLeft--;
}
}
return result.length;
}
Array.prototype.move = function(from, to) {
this.splice(to, 0, (this.splice(from, 1))[0]);
return this.join("");
};
function totalNumPatterns(numOfRotatingItems) {
var iter = 1;
for (var q = numOfRotatingItems; q > 1; q--) {
iter *= q;
}
return iter;
}
function noDoubleLettersPresent(str) {
if (str.match(/(.)\1/g)) {
return false;
} else {
return true;
}
}
permAlone('abcdefa');
I think the problem was your permutation algorithm; where did you get that from? I tried it with a different one (after Filip Nguyen, adapted from his answer to this question) and it returns 3600 as expected.
function permAlone(str) {
var result = 0;
var fact = [1];
for (var i = 1; i <= str.length; i++) {
fact[i] = i * fact[i - 1];
}
for (var i = 0; i < fact[str.length]; i++) {
var perm = "";
var temp = str;
var code = i;
for (var pos = str.length; pos > 0; pos--) {
var sel = code / fact[pos - 1];
perm += temp.charAt(sel);
code = code % fact[pos - 1];
temp = temp.substring(0, sel) + temp.substring(sel + 1);
}
console.log(perm);
if (! perm.match(/(.)\1/g)) result++;
}
return result;
}
alert(permAlone('abcdefa'));
UPDATE: In response to a related question, I wrote an algorithm which doesn't just brute force all the permutations and then skips the ones with adjacent doubles, but uses a logical way to only generate the correct permutations. It's explained here: Permutations excluding repeated characters and expanded to include any number of repeats per character here: Generate all permutations of a list without adjacent equal elements
I agree with m69, the bug seems to be in how you are generating permutations. I got 3600 for 'abcdefa' by implementing a different algorithm for generating permutations. My solution is below. Since it uses recursion to generate the permutations the solution is not fast, however you may find the code easier to follow, if speed is not important.
The reason for having a separate function to generate the array index values in the permutations was to verify that the permutation code was working properly. Since there are duplicate values in the input strings it's harder to debug issues in the permutation algorithm.
// Simple helper function to compute all permutations of string indices
function permute_indices_helper(input) {
var result = [];
if (input.length == 0) {
return [[]];
}
for(var i = 0; i < input.length; i++) {
var head = input.splice(i, 1)[0];
var tails = permute_indices_helper(input);
for (var j = 0; j < tails.length; j++) {
tails[j].splice(0, 0, head);
result.push(tails[j]);
}
input.splice(i, 0, head); // check
}
return result;
};
// Given an array length, generate all permutations of possible indices
// for array of that length.
// Example: permute_indices(2) generates:
// [[0,1,2], [0,2,1], [1,0,2], ... , [2, 0, 1]]
function permute_indices(array_length) {
var result = [];
for (var i = 0; i < array_length; i++) {
result.push(i);
}
return permute_indices_helper(result);
}
// Rearrange letters of input string according to indices.
// Example: "car", [2, 1, 0]
// returns: "rac"
function rearrange_string(str, indices) {
var result = "";
for (var i = 0; i < indices.length; i++) {
var string_index = indices[i];
result += str[string_index];
}
return result;
}
function permAlone(str) {
var result = 0;
var permutation_indices = permute_indices(str.length);
for (var i = 0; i < permutation_indices.length; i++) {
var permuted_string = rearrange_string(str, permutation_indices[i]);
if (! permuted_string.match(/(.)\1/g)) result++;
}
return result;
}
You can see a working example on JSFiddle.
Let's say I'm writing a function like so:
function longestString (someArray) {
// code
}
If someArray = ['word','longer phrase',['a','b','c'],1234567891011121314151617], I would want the function to only return the longest string in the array and ignore the integers and other arrays that may also lie within it. I tried this:
function longestString (someArray) {
return someArray.sort(function (a, b) { return b.length - a.length; })[0];
}
It didn't work, and I am now stuck. :/
Filter only string element and do it
function longestString (someArray) {
return someArray
.filter(function(a){ return typeof(a)=='string' })
.sort(function (a, b) { return b.length - a.length; })[0];
}
Try this:
function longestString(someArray) {
var result = "";
for (var i = 0; i < someArray.length; i++) {
if ((typeof someArray[i] === "string") && (someArray[i].length > result.length)) {
result = someArray[i];
}
}
return result;
}
try to do :
function longestString (someArray) {
$longest_string = '';
foreach ($someArray as $value)
{
$current_length = strlen($longest_string);
if(strlen($value) > $current_length ) $longest_string = $value;
}
return $longest_string;
}
Try this.
var a = ['word', 'longer phrase', ['a', 'b', 'c'], 1234567891011121314151617];
returnLongestString(a);
function returnLongestString(arr) {
var longestString = '';
for (var i = 0; i < arr.length; i++) {
if (typeof arr[i] == "string" && arr[i].length > longestString.length) {
longestString = arr[i];
}
};
return longestString;
}
When I saw this question, it had 0 answers, when I finished writing and testing my function, there were five. But this is my approach:
The key here is to first filter only the strings. Then, list all the lengths on an array. Then using that array you can get a match on the bigger one.
function longestString (someArray) {
//we only need strings, so first we will filter all the data
var stringsOnly = [];
for (var i = 0; i < someArray.length; i++) {
if(typeof(someArray[i]) === 'string'){
stringsOnly.push(someArray[i]);
}
};
//Now with an array of just strings, we can get their indivial lenghts
var stringLengths = [];
for (var i = 0; i < stringsOnly.length; i++) {
var currentString = stringsOnly[i];
stringLengths.push(currentString.length);
};
//Get the max length
var maxLength = Math.max.apply(Math,stringLengths);
//get a string wich length equals to maxLength
for (var i = 0; i < stringsOnly.length; i++) {
var theString = stringsOnly[i];
if(theString.length === maxLength){return theString};
};
}
This function will return the largest string. If more than one string have the same length, It will return the first one. However, if you want to get various strings, you could make some little modificationson the function above:
function multipleLongestString (someArray) {
//we only need strings, so first we will filter all the data
var stringsOnly = [];
for (var i = 0; i < someArray.length; i++) {
if(typeof(someArray[i]) === 'string'){
stringsOnly.push(someArray[i]);
}
};
//Now with an array of just strings, we can get their indivial lenghts
var stringLengths = [];
for (var i = 0; i < stringsOnly.length; i++) {
var currentString = stringsOnly[i];
stringLengths.push(currentString.length);
};
//Get the max length
var maxLength = Math.max.apply(Math,stringLengths);
//modification here
longests = [];
//get a string wich length equals to maxLength
for (var i = 0; i < stringsOnly.length; i++) {
var theString = stringsOnly[i];
if(theString.length === maxLength){longests.push(theString)};
};
return longests;
}
That is an extra that may help you later. But if you just want the largest one, use the first function. I hope that my answer is relevant.
:)
Heres my approach at it. Really all you want to know is if the phrase is longer than the previous and if its a string.
jsFiddle here.
var someArray = ['word','longer phrase',['a','b','c'],1234567891011121314151617]
var longestString = function(arr) {
var longest = "";
for (var i = 0; i < arr.length; i++) {
var value = arr[i];
if (typeof value === "string") {
longest = arr[i];
}
}
alert(longest);
}
longestString(someArray);