This is one of freecodecamps challenges it passes the for loop inside the filter passes the first element of the array newArg but doesn't for the second one and so on therefore the challenge doesn't pass can someone explain to me why. Please don't write any full solutions as i just want a little help to move forward.
function destroyer(arr) {
// Remove all the values
var newArg = [];
for (var i=1; i < arguments.length; i++){
newArg.push(arguments[i]);
}
var newArray = arr.filter(function(val){
for (i = 0; i < newArg.length; i++) {
return val !== newArg[i];
}
});
return newArray;
}
destroyer([1, 2, 3, 1, 2, 3], 2, 3);
The filter call:
var newArray = arr.filter(function(val){
for (i = 0; i < newArg.length; i++) {
return val !== newArg[i];
}
});
is the same as:
var newArray = arr.filter(function(val) {
return val !== newArg[0];
});
because you are returning from the very first iteration.
Solution:
You'll have to wrap the return statement in an if like this:
var newArray = arr.filter(function(val){
for (i = 0; i < newArg.length; i++) {
if(val === newArg[i]) { // don't return if val !== newArg[i]
return true; // return only when they're ===
}
}
return false; // default return (nothing is found in the array)
});
Or use an alternative such as Array.prototype.some like this:
var newArray = arr.filter(function(val){
return newArg.some(function(arg) { // return true if some item pass the test (false otherwise)
return arg === val; // the test
})
});
Related
I canĀ“t understand in this particular script how reduce works. I though that reduce always treats first argument as a acumulator, but in this ocassion the var result = [] seems to be the acumulator or maybe I am wrong. Initially I understood that fist argument of function symDiff (arrayOne) should be the accumulator for reduce method.
function sym() {
var args = [];
for (var i = 0; i < arguments.length; i++) {
args.push(arguments[i]);
}
function symDiff(arrayOne, arrayTwo) {
var result = [];
arrayOne.forEach(function(item) {
if (arrayTwo.indexOf(item) < 0 && result.indexOf(item) < 0) {
result.push(item);
}
});
arrayTwo.forEach(function(item) {
if (arrayOne.indexOf(item) < 0 && result.indexOf(item) < 0) {
result.push(item);
}
});
return result;
}
// Apply reduce method to args array, using the symDiff function
return args.reduce(symDiff);
}
sym([1, 2, 3], [5, 2, 1, 4]);
Write a mySort function which takes in an array of integers, and should return an array of the inputted integers sorted such that the odd numbers come first and even numbers come last.
So:
mySort([90, 45, 66, 'bye', '100.5'])
should return
[45, 66, 90, 100].
Here is my code:
function mySort(array) {
var strArray = [];
var oddArray = [];
var evenArray = [];
var sortedArray = [];
var arrayLength = array.length
for (var i = 0; i <= arrayLength; i++) {
if (array[i] === 'string') {
strArray = array[i].push();
}
if (Math.floor().array[i] % 2 === 0) {
evenArray = array[i].push();
}
if (Math.floor().array[i] % 2 !== 0) {
oddArray = array[i].push();
}
}
sortedArray = sort(oddArray) + sort(evenArray);
}
console.log(mySort[90, 45, 66, 'bye', 100.5]);
Several errors.
You didn't return:
function mySort(array) {
// ...
return sortedArray;
}
You should pass the parameter to Math.floor:
Math.floor(array[i]);
You should pass the parameter to array.push:
strArray.push(array[i]);
evenArray.push(array[i]);
oddArray.push(array[i]);
You should concat:
sortedArray = oddArray.concat(evenArray);
Now it at least runs.
You should use typeof: (sorts string)
if (typeof array[i] === 'string') {
// ...
}
You should use else if: (removes string)
if (typeof array[i] === 'string') {
// ...
}
else if (Math.floor(array[i]) % 2 === 0) {
// ...
}
else if (Math.floor(array[i]) % 2 !== 0) {
// ...
}
Your for loop should end earlier: (removes undefined)
for (var i = 0; i < arrayLength; i++) {
// ...
}
You should push the floor:
evenArray.push(Math.floor(array[i]));
oddArray.push(Math.floor(array[i]));
Finally, sort it in order using a comparator:
sortedArray.sort(function (a, b) { return a - b; })
Solution:
function mySort(array) {
var strArray = [];
var oddArray = [];
var evenArray = [];
var sortedArray = [];
var arrayLength = array.length;
for (var i = 0; i < arrayLength; i++) {
if (typeof array[i] === 'string') {
strArray.push(array[i]);
}
else if (Math.floor(array[i]) % 2 === 0) {
evenArray.push(Math.floor(array[i]));
}
else if (Math.floor(array[i]) % 2 !== 0) {
oddArray.push(Math.floor(array[i]));
}
}
sortedArray = oddArray.concat(evenArray);
sortedArray.sort(function (a, b) { return a - b; });
return sortedArray;
}
console.log(mySort([90, 45, 66, 'bye', 100.5])); // [45, 66, 90, 100]
You have no return statement. JavaScript function syntax doesn't implicitly return the last expression, except to return undefined if no explicit return is present.
You should .concat() the arrays. The + doesn't do what you seem to want.
return sort(oddArray).concat(sort(evenArray));
This condition is incorrect:
if(array[i] === 'string'){
You need typeof there to check the type of the member.
if(typeof array[i] === 'string'){
Your .push() calls are wrong. I guess you meant this:
evenArray.push(array[i]);
Your recursive calls should be using mySort() instead of sort().
strArray and sortedArray are essentially being ignored.
Math.floor() expects an argument.
Math.floor(array[i])
Your loop condition is wrong. It should be i < arrayLength, not <=
Your recursion has no escape clause
Your initial call to mySort is not using parentheses to invoke it. It should be:
console.log(mySort([/*...array items...*/]));
Your if conditions should be using else. If it's a string, you don't need to test it again, assuming it is to be excluded. If it's not even, then you know it's odd, based on your criteria, so the last condition isn't needed.
You apparently want to convert strings to numbers if possible, and converted to an integer. So instead of the typeof check, you could go ahead and convert it using parseInt or + or Number, and check if it's NaN, and if so, pass it over, and if not, make sure it's converted to an integer before testing it for odd/even.
Just to note, arrow functions do have an implicit return when the function body consists of a single expression.
Here's a working example with the above corrections:
function mySort(array) {
var oddArray = [];
var evenArray = [];
var arrayLength = array.length;
for(var i = 0; i < arrayLength; i++) {
var n = Math.floor(Number(array[i]));
if (isNaN(n)) {
continue;
}
if (n % 2 === 0 ){
evenArray.push(n);
} else {
oddArray.push(n);
}
}
return oddArray.length < 1 ? evenArray :
evenArray.length < 1 ? oddArray :
mySort(oddArray).concat(mySort(evenArray));
}
console.log(mySort([90, 45, 66, 'bye', 100.5]));
With a simple improvement on #llama 's code, expected result is returned.
We just need to sort oddArray and evenArray individually.
function mySort(nums) {
'use strict'
var array = nums
var strArray = [];
var oddArray = [];
var evenArray = [];
var sortedArray = [];
var arrayLength = array.length;
for (var i = 0; i < arrayLength; i++) {
if (typeof array[i] === 'string') {
strArray.push(array[i]);
}
else if (Math.floor(array[i]) % 2 === 0) {
evenArray.push(Math.floor(array[i]));
}
else if (Math.floor(array[i]) % 2 !== 0) {
oddArray.push(Math.floor(array[i]));
}
}
// sort oddArray
oddArray.sort(function (a, b) { return a - b; });
// sort evenArray
evenArray.sort(function (a, b) { return a - b; });
// make an array from both of them.
sortedArray = oddArray.concat(evenArray);
return sortedArray;
}
I want to remove the third occurrence of a character from a string.
Below is what I tried from my end:
function unique(list) {
var result = [];
function findOccurrences(arr, val) {
var i, j,
count = 0;
for (i = 0, j = arr.length; i < j; i++) {
(arr[i] === val) && count++;
}
return count;
}
$.each(list, function(i, e) {
if (findOccurrences(list, e) < 3) result.push(e);
});
return result.join("");
}
var srting = "DGHKHHNL";
var thelist = srting.split("")
console.log(unique(thelist));
Here are some expected results:
Input: DGHKHHNL
Expected: DGHKHNL
Input: AFKLABAYBIB
Expected: AFKLABYBI
Input: JNNNKNND
Expected: JNNKD
https://regex101.com/r/WmUPWW/1 .. I tried using this regex as well to solve the issue. But this this doesn't solves the issue as well.
Please help
Instead of counting the occurrences, you should check the occurrence count for the specific index you are evaluating. Basically, if it's the 3rd or more time that it has appeared, then you don't want it.
A slight change to your code can achieve this (you may want to choose a better function name):
function unique(list) {
var result = [];
function findOccurrenceIndex(arr, val, index) {
var i, j,
count = 0;
for (i = 0, j = arr.length; i < j; i++) {
(arr[i] === val) && count++;
if (i == index) {
return count;
}
}
return count;
}
$.each(list, function(i, e) {
if (findOccurrenceIndex(list, e, i) < 3) result.push(e);
});
return result.join("");
}
var srting = "DGHKHHNL";
var thelist = srting.split("")
console.log(unique(thelist));
Here is a working example
Note that this answer is based on your current code, I expect you could refactor the logic to reduce the code clutter.
In fact, the following reduces the code to a single loop. It works by building a dictionary of character counts as it works though the list. (It also doesn't rely on JQuery like your original attempt):
function unique(list) {
var result = [];
var counts = {};
for (var i = 0; i < list.length; i++) {
var c = list[i];
if (!counts[c])
counts[c] = 0;
counts[c]++;
if (counts[c] < 3) {
result.push(c);
}
}
return result.join("");
}
Here is a working example
An alternate approach which doesn't rely on jQuery (although you could easily swap that with a forEach):
function unique(str) {
var count = {}
return str.split("").reduce((acc, cur) => {
if (!(cur in count)) {
count[cur] = 1;
acc.push(cur);
return acc;
}
if (count[cur] == 2) return acc;
acc.push(cur);
count[cur]++;
return acc;
}, []).join("");
}
Here I used two helper array result and tempCount . tempCount is store each alphabet as key and count it ,so if it is exceed more than 3
function unique(list) {
var result = [];
var tempCount = [];
list = list.split("");
for(var i=0;i < list.length;i++) {
if(tempCount[list[i]]) {
if(tempCount[list[i]] == 2) continue;
tempCount[list[i]]++;
} else {
tempCount[list[i]] = 1;
}
result.push(list[i]);
}
return result.join("");
}
var srting = "JNNNKNND";
console.log(unique(srting));
Building off the answer by #musefan, another ES6 approach can use Array.reduce to build the counts/output based on an accumulator object:
const onlyTwo = list => list.split('').reduce((cache, letter) => {
cache[letter] ? cache[letter]++ : cache[letter] = 1;
if (cache[letter] < 3) cache.output += letter;
return cache;
}, {
output: ''
}).output;
console.log(onlyTwo('DGHKHHNL'));
console.log(onlyTwo('AFKLABAYBIB'));
console.log(onlyTwo('JNNNKNND'));
You can improve this by applying functional programming principles to separate the concerns of counting the duplicates and generating the output string. This way you can utilize the same accumulation technique with different max values.
const maxDuplicates = max => list => list.split('').reduce((cache, letter) => {
cache[letter] ? cache[letter]++ : cache[letter] = 1;
if (cache[letter] <= max) cache.output += letter;
return cache;
}, {
output: ''
}).output;
const onlyTwo = maxDuplicates(2);
console.log(onlyTwo('DGHKHHNL'));
console.log(onlyTwo('AFKLABAYBIB'));
console.log(onlyTwo('JNNNKNND'));
const onlyOne = maxDuplicates(1);
console.log(onlyOne('DGHKHHNL'));
console.log(onlyOne('AFKLABAYBIB'));
console.log(onlyOne('JNNNKNND'));
I am trying to reverse a list of numbers however I am getting an output of undefined.
I am using closure to do it
here is my code
function reverseANumber(aList) {
function reverse() {
var newList = [];
var j=0;
for(var i = aList.length - 1; i >= 0; i--)
{
newList[j] = aList[i];
j++;
}
return newList
}
reverse(aList);
}
aList=[3,2,3,1];
console.log(reverseANumber(aList));
I am getting undefined as output
I am expecting 1 3 2 3 as output
What is wrong with my code ?
Simple
function reverseMe (list){
return list.reverse();
};
reverseMe([1,3,2,3]); // returns 3,2,3,1
Do not reinvent the wheel :)
Use Reverse
var aList=[3,2,3,1];
aList.reverse();
console.log(aList)
Outputs:
[1, 3, 2, 3]
CODEPEN DEMO
You forgot to add a return statement before the reverse(aList) call:
function reverseANumber(aList) {
function reverse() {
var newList = [];
var j = 0;
for(var i = aList.length; i >= 0; i--) {
newList[j] = aList[i];
j++;
}
return newList;
}
return reverse(aList);
}
aList = [3,2,3,1];
console.log(reverseANumber(aList));
You just declared a function inside of a function, which won't work.
Try this:
function reverseANumber(aList) {
var newList = [];
var j=0;
for(var i = aList.length - 1; i >= 0; i--)
{
newList[j] = aList[i];
j++;
}
return newList;
}
reverse(aList);
}
aList=[3,2,3,1];
console.log(reverseANumber(aList));
function reverseANumber(aList) {
let lastIndex = aList.length - 1;
let result = [];
function reverse(aList, lastIndex) {
if (lastIndex === -1) {
return;
}
result.push(aList[lastIndex])
reverse(aList, lastIndex - 1);
}
reverse(aList, lastIndex);
return result;
}
This question already has answers here:
Remove duplicate values from JS array [duplicate]
(54 answers)
Closed 8 years ago.
I have the following script that's supposed to uniqualize array:
function uniques(arr) {
var a = [];
for (var i=0, l=arr.length; i<l; i++)
for (var j = 0; j < arr[i].length; j++) {
if (a.indexOf(arr[i][j]) === -1 && arr[i][j] !== '') {
a.push(arr[i][j]);
}
}
return a;
}
However, when it receives only one element, it just breaks it into the letters (which is understandable).
Do you know how I make it check if it's receiving only one element and then returns it back?
Thanks!
I'm not sure why you need the nested loop - you only need a single loop if you're processing a non-nested array:
function uniques(arr) {
if (arr.length === 1) { return arr };
var a = [];
for (var i = 0, l = arr.length; i < l; i++) {
if (a.indexOf(arr[i]) === -1) {
a.push(arr[i]);
}
}
return a;
}
DEMO
If you want to process nested arrays, use a recursive function. Here I've used underscore's flatten method as the basis:
function toType(x) {
return ({}).toString.call(x).match(/\s([a-zA-Z]+)/)[1].toLowerCase();
}
function flatten(input, output) {
if (!output) { output = []; }
for (var i = 0, l = input.length; i < l; i++) {
var value = input[i];
if (toType(value) !== 'array' && output.indexOf(value) === -1) {
output.push(value);
} else {
flatten(value, output);
}
}
return output.sort(function (a, b) { return a - b; });
};
var arr = [1, 2, 3, [[4]], [10], 5, 1, 3];
flatten(arr); // [ 1, 2, 3, 4, 5, 10 ]
DEMO
I think the solution is this:
function uniques(arr) {
if (arr.length > 1) {
var a = [];
for (var i=0, l=arr.length; i<l; i++)
for (var j = 0; j < arr[i].length; j++) {
if (a.indexOf(arr[i][j]) === -1 && arr[i][j] !== '') {
a.push(arr[i][j]);
}
}
return a;
}
else
{
return arr;
}
}
What you're trying to do is a linear search on the created matrix for each item in the original one.
The solution below will accomplish this, but at a great cost. If your original matrix is 50x50 with unique values in each cell, it will take you 50^3 (=125000) loops to exit the function.
The best technique to search, in programming science, takes O(log(N)) that means that if you'll use it on your problem it will take log(50^2) (=11) loops.
function uniques(arr) {
var items = [];
var a = arr.map(function(row, i) {
return row.map(function(cell, j) {
if (items.indexOf(cell) >= 0) {
items.push(cell);
return cell;
}
});
});
}