I am new to writing javascript and have started doing LeetCode. I am currently doing the Longest Common Prefix problem and have gotten to a point where the output has the expected output but followed by undefined. i.e expected output: "flower" my output: "flowerundefined".
Here is my code:
var longestCommonPrefix = function(strs) {
let arrayLen = strs.length
let strn = strs[0];
let len = strn.length;
let element = "";
if(strs.length == 1)
return strn;
if(strn == "")
return element;
element = strn[0];
for(let i = 0; i<len; i++)
{
let matches = strs.filter(s => s.includes(element));
// console.log(matches);
if(matches.length !== arrayLen)
{
var reverseElement = "";
for(let j = 0; j<i; j++)
reverseElement += strn[j];
return reverseElement;
}
else if(matches.length == arrayLen)
element += strn[i+1];
else
return element;
}
Here is the output:
LeetCode Output Post-Submission
Why Array.push doesnt work inside Nested For Loop? But it works if I replace 2nd for Loop with forEach
var longestCommonPrefix = function (strs) {
if (strs.length === 1) {
return strs.join('')
}
let reference = strs[0].split('');
let answer = [];
let final = [];
for (let i = 1; i < strs.length; i++) {
let check = strs[i].split('')
for (let x = 0; x < reference.length; x++) {
if (reference[x] === check[x]) {
answer.push(check[x]) //WHY THIS WONT WORK?
} else return
}
reference = answer
}
console.log(answer)
};
longestCommonPrefix(["flower", "flow", "flight"]);
return is used to exit the function, use break to only exit the loop
var longestCommonPrefix = function(strs) {
if (strs.length === 1) {
return strs.join('')
}
let reference = strs[0].split('');
let answer = [];
let final = [];
for (let i = 1; i < strs.length; i++) {
let check = strs[i].split('')
for(let x = 0 ; x<reference.length ; x++){
if(reference[x] === check[x]){
answer.push(check[x]) //WHY THIS WONT WORK?
}else break
}
reference = answer
}
console.log(answer)
};
longestCommonPrefix(["flower", "flow", "flight"])
I'm trying the following logic and not sure which array function can help. I'm not able to use map or es6 but would like to see an answer.
I tried the following:
/* JS */ - This is not working and would like to see how to make it work.
var input = ['x','y','z'];
var powerSetResult = powerSet(input);
console.log(powerSetResult);
/*Ouput should be [''.'x','y','z','xy,'xz','yz','xyz']*/
function powerSet(arr) {
var data = [];
for(var i=0; i<arr.length; i++) {
arr[i] = arr[i] + arr[i+1];
data.push(arr[i]);
}
console.log(data);
return data;
}
/* ES 6 */ - Is there a better way to do this?
let input = ['x','y','z'];
let powerSetResult = powerSet(input);
console.log(powerSetResult);
/*Ouput should be [''.'x','y','z','xy,'xz','yz','xyz']*/
const powerSet(arr) {
let data = arr.map(([s1, s2, s3]) => [``,`${s1}`,`${s2}`,`${s3}`,`${s1}${s2}`,`${s1}${s3}`,`${s2}${s3}`,`${s1}${s2}${s3}`]);
console.log(data);
return data;
}
Certainly not the most efficient... but you could do this:
var input = ['x','y','z'];
var powerSetResult = powerSet(input);
console.log(powerSetResult);
function powerSet(arr, result) {
result = result || new Set();
const str = arr.join('');
for (let i = 0; i < arr.length; i++) {
for (let j = i; j <= arr.length; j++) {
result.add(str.slice(i, j));
}
powerSet([...arr.slice(0, i), ...arr.slice(i+1)], result)
}
return Array.from(result).sort((a, b) => {
return (a.length - b.length) || a.localeCompare(b);
});
}
/* Output should be [''.'x','y','z','xy,'xz','yz','xyz'] */
Caveat being it will only work for single letter elements, but is easily modifiable to accommodate more.
how can i get elements uniquely from an array if aa is twice time it should not count in a result if it is if a is three times it should count 1
var string = "aaabbccddde" // Expected result ade
var toArray = string.split("")
console.log(toArray)
var newArr = []
for(let i =0; i<toArray.length; i++) {
if(newArr.indexOf(toArray[i]) === -1) {
newArr.push(toArray[i])
}
}
console.log(newArr)
can't find the solution yet please guide thank
Maybe this function can help you:
function getUniques(str) {
const uniques = [];
const strs = str.split("");
for (let i = 0; i < strs.length; i++) {
const elm = strs[i];
for (let j = i; j < strs.length; j++) {
if(elm === uniques[uniques.length - 1]) break;
if (elm !== strs[j + 1]) {
uniques.push(elm);
break;
}
}
}
return uniques.join("");
}
Sample:
getUniques("aaaadaaabbbcccdeeeee22222222222232") // adabcde232
Okay, so I've been working on a sort function for my application, and I've gotten stuck.
Here's my fiddle.
To explain briefly, this code starts with an array of strings, serials, and an empty array, displaySerials:
var serials = ["BHU-009", "BHU-008", "BHU-001", "BHU-010", "BHU-002", "TYU-970", "BHU-011", "TYU-969", "BHU-000"];
var displaySerials = [];
The aim of these functions is to output displaySerials as an array of objects with two properties: beginSerial and endSerial. The way that this is intended to work is that the function loops through the array, and tries to set each compatible string in a range with each other, and then from that range create the object where beginSerial is the lowest serial number in range and endSerial is the highest in range.
To clarify, all serials in a contiguous range will have the same prefix. Once that prefix is established then the strings are broken apart from the prefix and compared and sorted numerically.
So based on that, the desired output from the array serials would be:
displaySerials = [
{ beginSerial: "BHU-008", endSerial: "BHU-011" },
{ beginSerial: "BHU-000", endSerial: "BHU-002" },
{ beginSerial: "TYU-969", endSerial: "TYU-970" }
]
I've got it mostly working on my jsfiddle, the only problem is that the function is pushing one duplicate object into the array, and I'm not sure how it is managing to pass my checks.
Any help would be greatly appreciated.
Marc's solution is correct, but I couldn't help thinking it was too much code. This is doing exactly the same thing, starting with sort(), but then using reduce() for a more elegant look.
var serials = ["BHU-009", "BHU-008", "BHU-001", "BHU-010", "BHU-002", "TYU-970", "BHU-011", "TYU-969", "BHU-000"]
serials.sort()
var first = serials.shift()
var ranges = [{begin: first, end: first}]
serials.reduce(mergeRange, ranges[0])
console.log(ranges) // the expected result
// and this is the reduce callback:
function mergeRange(lastRange, s)
{
var parts = s.split(/-/)
var lastParts = lastRange.end.split(/-/)
if (parts[0] === lastParts[0] && parts[1]-1 === +lastParts[1]) {
lastRange.end = s
return lastRange
} else {
var newRange = {begin: s, end: s}
ranges.push(newRange)
return newRange
}
}
I've got a feeling that it's possible to do it without sorting, by recursively merging the results obtained over small pieces of the array (compare elements two by two, then merge results two by two, and so on until you have a single result array). The code wouldn't look terribly nice, but it would scale better and could be done in parallel.
Nothing too sophisticated here, but it should do the trick. Note that I'm sorting the array from the get-go so I can reliably iterate over it.
Fiddle is here: http://jsfiddle.net/qyys9vw1/
var serials = ["BHU-009", "BHU-008", "BHU-001", "BHU-010", "BHU-002", "TYU-970", "BHU-011", "TYU-969", "BHU-000"];
var myNewObjectArray = [];
var sortedSerials = serials.sort();
//seed the object
var myObject = {};
var previous = sortedSerials[0];
var previousPrefix = previous.split("-")[0];
var previousValue = previous.split("-")[1];
myObject.beginSerial = previous;
myObject.endSerial = previous;
//iterate watching for breaks in the sequence
for (var i=1; i < sortedSerials.length; i++) {
var current = sortedSerials[i];
console.log(current);
var currentPrefix = current.split("-")[0];
var currentValue = current.split("-")[1];
if (currentPrefix === previousPrefix && parseInt(currentValue) === parseInt(previousValue)+1) {
//sequential value found, so update the endSerial with it
myObject.endSerial = current;
previous = current;
previousPrefix = currentPrefix;
previousValue = currentValue;
} else {
//sequence broken; push the object
console.log(currentPrefix, previousPrefix, parseInt(currentValue), parseInt(previousValue)+1);
myNewObjectArray.push(myObject);
//re-seed a new object
previous = current;
previousPrefix = currentPrefix;
previousValue = currentValue;
myObject = {};
myObject.beginSerial = current;
myObject.endSerial = current;
}
}
myNewObjectArray.push(myObject); //one final push
console.log(myNewObjectArray);
I would use underscore.js for this
var bSerialExists = _.findWhere(displaySerials, { beginSerial: displaySettings.beginSerial });
var eSerialExists = _.findWhere(displaySerials, { endSerial: displaySettings.endSerial });
if (!bSerialExists && !eSerialExists)
displaySerials.push(displaySettings);
I ended up solving my own problem because I was much closer than I thought I was. I included a final sort to get rid of duplicate objects after the initial sort was finished.
var serials = ["BHU-009", "BHU-008", "BHU-001", "BHU-010", "BHU-002", "TYU-970", "BHU-011", "TYU-969", "BHU-000"];
var displaySerials = [];
var mapSerialsForDisplay = function () {
var tempArray = serials;
displaySerials = [];
for (var i = 0; i < tempArray.length; i++) {
// compare current member to all other members for similarity
var currentSerial = tempArray[i];
var range = [currentSerial];
var displaySettings = {
beginSerial: currentSerial,
endSerial: ""
}
for (var j = 0; j < tempArray.length; j++) {
if (i === j) {
continue;
} else {
var stringInCommon = "";
var comparingSerial = tempArray[j];
for (var n = 0; n < currentSerial.length; n++) {
if (currentSerial[n] === comparingSerial[n]) {
stringInCommon += currentSerial[n];
continue;
} else {
var currentRemaining = currentSerial.replace(stringInCommon, "");
var comparingRemaining = comparingSerial.replace(stringInCommon, "");
if (!isNaN(currentRemaining) && !isNaN(comparingRemaining) && stringInCommon !== "") {
range = compareAndAddToRange(comparingSerial, stringInCommon, range);
displaySettings.beginSerial = range[0];
displaySettings.endSerial = range[range.length - 1];
var existsAlready = false;
for (var l = 0; l < displaySerials.length; l++) {
if (displaySerials[l].beginSerial == displaySettings.beginSerial || displaySerials[l].endSerial == displaySettings.endSerial) {
existsAlready = true;
}
}
if (!existsAlready) {
displaySerials.push(displaySettings);
}
}
}
}
}
}
}
for (var i = 0; i < displaySerials.length; i++) {
for (var j = 0; j < displaySerials.length; j++) {
if (i === j) {
continue;
} else {
if (displaySerials[i].beginSerial === displaySerials[j].beginSerial && displaySerials[i].endSerial === displaySerials[j].endSerial) {
displaySerials.splice(j, 1);
}
}
}
}
return displaySerials;
}
var compareAndAddToRange = function (candidate, commonString, arr) {
var tempArray = [];
for (var i = 0; i < arr.length; i++) {
tempArray.push({
value: arr[i],
number: parseInt(arr[i].replace(commonString, ""))
});
}
tempArray.sort(function(a, b) {
return (a.number > b.number) ? 1 : ((b.number > a.number) ? -1 : 0);
});
var newSerial = {
value: candidate,
number: candidate.replace(commonString, "")
}
if (tempArray.indexOf(newSerial) === -1) {
if (tempArray[0].number - newSerial.number === 1) {
tempArray.unshift(newSerial)
} else if (newSerial.number - tempArray[tempArray.length - 1].number === 1) {
tempArray.push(newSerial);
}
}
for (var i = 0; i < tempArray.length; i++) {
arr[i] = tempArray[i].value;
}
arr.sort();
return arr;
}
mapSerialsForDisplay();
console.log(displaySerials);
fiddle to see it work
Here's a function that does this in plain JavaScript.
var serials = ["BHU-009", "BHU-008", "BHU-001", "BHU-010", "BHU-002", "TYU-970", "BHU-011", "TYU-969", "BHU-000"];
function transformSerials(a) {
var result = []; //store array for result
var holder = {}; //create a temporary object
//loop the input array and group by prefix
a.forEach(function(val) {
var parts = val.split('-');
var type = parts[0];
var int = parseInt(parts[1], 10);
if (!holder[type])
holder[type] = { prefix : type, values : [] };
holder[type].values.push({ name : val, value : int });
});
//interate through the temp object and find continuous values
for(var type in holder) {
var last = null;
var groupHolder = {};
//sort the values by integer
var numbers = holder[type].values.sort(function(a,b) {
return parseInt(a.value, 10) > parseInt(b.value, 10);
});
numbers.forEach(function(value, index) {
if (!groupHolder.beginSerial)
groupHolder.beginSerial = value.name;
if (!last || value.value === last + 1) {
last = value.value;
groupHolder.endSerial = value.name;
if (index === numbers.length - 1) {
result.push(groupHolder);
}
}
else {
result.push(groupHolder);
groupHolder = {};
last = null;
}
});
}
return result;
}
console.log(transformSerials(serials));
<script src="http://gh-canon.github.io/stack-snippet-console/console.min.js"></script>