I need to compare the elements of two arrays to know if the first index is greater than the other one and vice versa but my if statement is not working.
function winround(arr, arr2) {
var set = Array.from(new Set(arr))
var set2 = Array.from(new Set(arr2))
var uniqueItems = set.sort(function(a, b) {
return b - a
});
var uniqueItems2 = set2.sort(function(a, b) {
return b - a
});
for (var i in uniqueItems)
if (uniqueItems[0] > uniqueItems2[0])
return "true";
else {
for (var i in uniqueItems2)
if (uniqueItems[0] < uniqueItems2[0])
return "false";
}
}
winround([2, 1, 5, 4, 4, 3, 2, 1], [8, 6, 7]);
You should avoid using for(var i in uniqueItems) . The purpose of the for-in statement is to enumerate over object properties.
Instead of this use:
for (var i = 0; i < uniqueItems.length; i++) {
/* your code here */
}
Inside for loop of else part, you are always comparing the 1st element of 1st array with 1st element of 2nd array.
i.e., uniqueItems[0] < uniqueItems2[0]
It should be: uniqueItems[0] < uniqueItems2[i]
The following should give you the answer in a much simpler way:
function winround(arr, arr2) {
return Math.max(...arr)>Math.max(...arr2);
}
console.log(winround([2,1,5,4,4,3,2,1], [8,6,7]));
Related
I want filter the missing number from an sequential array using javascript but I am getting the wrong value. I am explaining my code below.
let arr1 = [1,2,3,4,5,6,7,8,10];
arr1 = arr1.filter((item,pos) => {
if(pos < arr1.length && arr1[pos+1] !== undefined) {
if(item !== arr1[pos+1]-1){
//console.log(item,arr1[pos+1]-1);
return arr1[pos+1]-1;
}
}
})
console.log(arr1);
Here 9 is missing from my array but I am getting the output [8] as output.
You need a different approach, because your filtering returns only a value which is in the array, not missing. As well as you not getting holes of more than one value.
This solution iterates the array and takes a variable for the expected value and if this value is smaller than the array value, it iterates until the given value from the array.
let array = [1, 2, 3, 6, 7, 8, 10],
missing = [],
value = array[0],
i;
for (i = 0; i < array.length; i++) {
while (value < array[i]) missing.push(value++);
++value;
}
console.log(missing);
filter method returns only existing elements which are evaluated to true in callback function:
filter() calls a provided callback function once for each element in
an array, and constructs a new array of all the values for which
callback returns a value that coerces to true.
So filter method cannot return incremented values from existing array.
You can use reduce method for finding gaps:
let arr1 = [1,2,3,4,5,6,7,8,10];
arr1 = arr1.reduce((a, c, i) => {
if ((c + 1) < arr1[i + 1])
a.push(c + 1);
return a;
}, [])
console.log(arr1);
As already said, you can't use filter as its purpose is to filter the values of the given array.
You could try using reduce in order to find multiple gaps:
let arr1 = [1, 2, 4, 5, 6, 7, 8, 12];
arr1 = arr1.reduce((carry, item, index) => {
item++;
while (index !== arr1.length - 1 && item < arr1[index + 1]) {
carry.push(item++);
}
return carry;
}, []);
console.log(arr1);
You can do it as below. Here iterating over all items and check if the difference between current item and previous of current item is 1 or not if not then return (current item -1).
let arr1 = [1,2,3,4,5,6,7,8,10];
for(var i = 1; i < arr1.length; i++) {
if(arr1[i] - arr1[i-1] != 1) {
console.log(arr1[i]-1);
}
}
Given a sequence of integers as an array, determine whether it is possible to obtain a strictly increasing sequence by removing no more than one element from the array.
For sequence = [1, 3, 2, 1], the output should be
almostIncreasingSequence(sequence) === false
There is no one element in this array that can be removed in order to get a strictly increasing sequence.
For sequence = [1, 3, 2], the output should be
almostIncreasingSequence(sequence) === true
As you can remove 3 from the array to get the strictly increasing sequence [1, 2]. Alternately, you can remove 2 to get the strictly increasing sequence [1, 3].
Here is what I have so far:
function almostIncreasingSequence(sequence) {
//compare current int to previous, return true if greater than
//remove int at index and compare with new values, return false if comparison fails
var result = false;
for(var i = 0; i < sequence.length; i++){
var newSequence = sequence.slice();
var subSequence = newSequence.splice(i, 1);
for(var j = 0; j < newSequence.length - 1; j++){
if(newSequence === newSequence.sort((a,b) => a < b).reverse()){
result = true;
}
}
}
return result;
}
I'm trying to figure out how to solve this problem. I feel like I'm very close but for some reason when I call reverse in the conditional statement it also sorts out the newSequence variable. It's sorting two variables in the conditional, not one. As a result it resolves to true. I'm not clear why this is happening. Any feedback is appreciated.
There is no need to use a nested loop, nor to create new arrays. This can be done in O(n) time:
function almostIncreasingSequence(sequence) {
var prev = -Infinity,
beforePrev = -Infinity,
allowExceptions = true;
for (var curr of sequence) {
// Is order not maintained?
if (curr <= prev) {
// Give up when this is not the first exception
if (!allowExceptions) return false;
allowExceptions = false;
// Decide whether to skip the current or previous value
if (curr > beforePrev) prev = curr;
} else { // Normal case: keep track of two preceding values
beforePrev = prev;
prev = curr;
}
}
return true;
}
console.log(almostIncreasingSequence([1,5,3,4,8])); // true
console.log(almostIncreasingSequence([1,5,0,6,8])); // true
console.log(almostIncreasingSequence([1,5,0,4,8])); // false
sort() modifies the array in place, it doesn't return a new array. And you can't compare the contents of two arrays using ==, so that's not a good way to tell if an array is sorted. You can simply loop through the array, testing if each element is greater than the previous one.
function almostIncreasingSequence(sequence) {
for (var i = 0; i < sequence.length; i++) {
var newSequence = sequence.slice();
newSequence.splice(i, 1);
var isSorted = true;
for (j = 1; isSorted && j < newSequence.length; j++) {
if (newSequence[j] <= newSequence[j-1]) {
isSorted = false;
}
}
if (isSorted) {
return true;
}
}
return false;
}
console.log(almostIncreasingSequence([1, 3, 2, 1]));
console.log(almostIncreasingSequence([1, 3, 2]));
console.log(almostIncreasingSequence([1, 2, 3, 4, 5, 3]));
console.log(almostIncreasingSequence([8, 1, 2, 3, 4, 5]));
console.log(almostIncreasingSequence([8, 1, 2, 2, 4, 5]));
I'd like to find the symmetric difference between TWO arrays.
This implementation works, however I'd like to write a function that is specific to only two arrays, rather than one that finds the symmetric difference between a bunch of arrays. The function should like this:
function diffArray(arr1, arr2) { }
then return a new array with the symmetric difference.
My best attempt so far was
var newArr = [];
for (var i = 0; i < arr1.length; i++){
var x = arr[i];
for (var n = 0; n < arr2.length; n++){
var y = arr2[n];
if (y === x){
break;
} else {
newArr.push(y);
}
}
}
However, I know this is not even close. The question (it is an algorithm problem for FreeCodeCamp) hints to use the methods array.filter(), array.indexOf(), array.concat(), array.slice() in the implementation.
I understand that the general idea is to take each element in one of the arrays (the first one in my case), then compare it to every element in the second array. If no matches are found, push that element into the newArr.
Can anyone help with a sound implementation that uses the aforementioned methods and provide a solid explanation/comments on how it works?
Thank you!
Here is another idea:
function diffArray(arr1, arr2) {
var newArr = [];
return arr1.filter(function(val) {
return arr2.indexOf(val) === -1;
})
/*the method above, returns a new array, so you can chain it
to concat with the array returned from the filter() method
in the arr2...*/
.concat(arr2.filter(function(val) {
return arr1.indexOf(val) === -1;
}));
}
This is my simple solution
function diffArray(a, b){
c = a.concat(b)
d = [];
var diffarr = c.filter(function(c1){
if (a.indexOf(c1) === -1 || b.indexOf(c1) === -1){
d.push(c1)
}
})
return d;}
diffArray([1, 2, 3, 5], [1, 2, 3, 4, 5]);
Alright. I solved it, but I think it can still be done better.
function diffArray(arr1, arr2) {
var newArray = [];
function inArray2(value){
if(arr2.indexOf(value) == -1){
return true;
}
return false;
}
function inArray1(value){
if(arr1.indexOf(value) == -1){
return true;
}
return false;
}
var arr1Filtered = arr1.filter(inArray2);
var arr2Filtered = arr2.filter(inArray1);
newArray = arr1Filtered.concat(arr2Filtered);
return newArray;
}
Since this passed all the test cases, I assume it is correct for all cases. Whew.
UPDATE: New and improved algorithm, thanks to helpful input from torazaburo. Hope this helps anyone who is also stuck on this challenge.
function diffArray(arr1, arr2) {
var newArray = [];
function notInArray2(value){
return arr2.indexOf(value) === -1;
}
function notInArray1(value){
return arr1.indexOf(value) === -1;
}
var arr1Filtered = arr1.filter(notInArray2);
var arr2Filtered = arr2.filter(notInArray1);
newArray = arr1Filtered.concat(arr2Filtered);
return newArray;
}
This can be solved by combining multiple array methods.
Below solution uses concat, reduce and includes.
function arrayDifference(arr1, arr2) {
return arr1
.concat(arr2)
.filter(item => !arr1.includes(item) || !arr2.includes(item));
}
console.log(arrayDifference([1, 2, 5], [1, 2, 3, 4, 5, 4])) // [3, 4, 4]
console.log(arrayDifference([1, 2, 5, 4], [1, 2, 3, 4])) // [5, 3]
I am rather new to JS and I was working on a problem that asked to split an array (first argument) into groups the length of size (second argument) and returns them as a multidimensional array.
I got the problem to work right for all test cases but it suggested using the array `push()` method. I tried it multiple times and couldn't ever get it to work right. I think I was getting messed up with arrays being by reference. I eventually declared a new Array for each element. I went with a more classic deep copy each element at a time. I Didn't go back and try the `push()` method again. There has to be a more efficient way to do this. I want to write good code. Would love to see better versions please.
Thanks!
function chunk(arr, size) {
var group = 0;
var counter = 0;
var even = false;
var odd = false;
if (arr.length % size === 0) {
group = arr.length / size;
even = true;
} else {
group = Math.ceil(arr.length / size);
odd = true;
}
var newArr = new Array(group);
for (var i = 0; i < group; i++) {
newArr[i] = new Array(size);
}
for (i = 0; i < group; i++) {
for (var j = 0; j < size && counter < arr.length; j++) {
newArr[i][j] = arr[counter++];
}
}
return newArr;
}
chunk(['a', 'b', 'c', 'd'], 2);
Using Array.prototype.slice, the function can be written in a shorter way:
function chunk(array, size) {
var result = []
for (var i=0;i<array.length;i+=size)
result.push( array.slice(i,i+size) )
return result
}
You can try the slice method from the Array object. Here's an idea on how to use it.
var arr = [1, 2, 3, 4, 5, 6];
var newArr = [];
newArr.push(arr.slice(0, arr.length / 2));
newArr.push(arr.length / 2, arr.length);
This is just an shallow implementation but you can use the same concept inside a better written function.
Here's an example function:
var arr = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14];
function toChunks(arr, size) {
var i = 0,
chunks = [];
for (; i < arr.length; i += size) {
chunks.push(arr.slice(i, i + size););
}
return chunks;
}
toChunks(arr, 2);
Hi I'm struggling to solve this problem. How to create a javascript function that takes any number of arrays as arguments, then returns an array of elements that only appear in one of the arrays. All items that appear in multiple arrays are removed. Getting nowhere with a solution, suspect I'm not approaching it in the right way, stumped!
Edit: the other question addresses eliminating duplicate values in one array, I need to compare x number of separate arrays and return the values that aren't duplicated between arrays. So ([5,6,7],[5,8,9]) returns [6,7,8,9].
function sym(args) {
var ans = [];
for(var i =0;i<arguments.length;i++){
var tempArr = arguments[i].filter(function(el){
var filtTrue = false;
for(var j = 0;j<arguments.length;j++){
if(Array.isArray(arguments[j]) && arguments[j] !== arguments[i]){
if(arguments[j].indexOf(el) === -1){
filtTrue = true;
}}
}
return filtTrue;
});
ans = ans.concat(tempArr);
}
return ans;
}
Here's one way to do it. The idea here is that you create a map for keeping counts of all the items in the array. You then cycle through each array, look up each value in the map and, if found, you increment its count. If not found, you set the count to 1. Then, when done with all the arrays, you collect any items that have a count of 1.
You weren't specific about what to do if an item appears more than once in the same array, but not in any other array. This first solution will not include that item (since it detects duplicates). It could be adapted (with a little more complexity) to allow that item if that was an issue (see 2nd code block below for that implementation).
function sym(/* pass one or more arrays here */) {
var ans = [], cnts = {};
//count all items in the array
for (var i = 0; i < arguments.length; i++){
arguments[i].forEach(function(item) {
if (cnts.hasOwnProperty(item)) {
// increase cnt
++cnts[item].cnt;
} else {
// initalize cnt and value
cnts[item] = {cnt: 1, val: item};
}
});
}
for (var item in cnts) {
if (cnts.hasOwnProperty(item) && cnts[item].cnt === 1) {
ans.push(cnts[item].val);
}
}
return ans;
}
If you want to include items that are present more than once in a single array, but not present in any other array, then you can use this slightly more complicated adaptation:
function sym(/* pass one or more arrays here */) {
var ans = [], cnts = {}, currentMap;
//count all items in the array
for (var i = 0; i < arguments.length; i++){
currentMap = {};
arguments[i].forEach(function(item) {
// if we haven't already counted this item in this array
if (!currentMap.hasOwnProperty(item)) {
if (cnts.hasOwnProperty(item)) {
// increase cnt
++cnts[item].cnt;
} else {
// initalize cnt and value
cnts[item] = {cnt: 1, val: item};
}
}
// keep track of whethere we've already counted this item in this array
currentMap[item] = true;
});
}
// output all items that have a cnt of 1
for (var item in cnts) {
if (cnts.hasOwnProperty(item) && cnts[item].cnt === 1) {
ans.push(cnts[item].val);
}
}
return ans;
}
Working demo: http://jsfiddle.net/jfriend00/bete5k3n/
I know this is increadibly late but this is another way to do it. Maybe not the most rigorous one but certainly creative. The method Array.symmetricDifference() expects any number of arguments and returns the symmetric difference of those arguments.
Array.prototype.symmetricDifference = function() {
var args = [];
// copy arguments into a real array and get rid of duplicates with filter
for(var i = 0; i < arguments.length; i++) {
args[i] = arguments[i];
args[i] = args[i].filter(function(item, pos, self) {
return self.indexOf(item) == pos;
});
}
var diff = args[0];
// iterate through every arguments in args.
// concatenate the first two arguments to form a new set.
// now every number in this new set that was contained in both arguments
// from before will be contained at least twice in this new set.
for(var j = 1; j < args.length; j++) {
//sort the new set so that duplicates are next to each other.
diff = diff.concat(args[j]).sort();
var index = 0;
// now iterate through the new set and delete both duplicates if you
// find any. Otherwise proceed to the next index.
while(index < diff.length) {
// if duplicate is found delete both, otherwise look at next index.
diff[index] === diff[index + 1] ? diff.splice(index, 2) : index++;
}
}
return diff;
};
You can invoke that method on any array or create a new one and invoke it on that one like this for example:
// take any number of arrays
var a = [3, 3, 3, 2, 5];
var b = [2, 1, 5, 7];
var c = [3, 4, 6, 6];
var d = [1, 2, 3];
var e = [5, 3, 9, 8];
var f = [1];
// invoke the method on "solution" with any number of arguments
// and store it in solution.
var solution = solution.symmetricDifference(a,b,c,d,e,f);
console.log(solution); // [1, 2, 4, 5, 6, 7, 8, 9]
I hope this helps!
Finding unique items in multiple arrays
function uniqueItemsInArrays(...args){
let allItems = [];
allItems = allItems.concat(...args)
return allItems.filter(function(item, pos, self) {
return self.indexOf(item) === pos && self.indexOf(item,pos+1) === -1;
});
}
uniqueItemsInArrays( [1, 5, 1, 8, 1, 2],
[2, 2, 9, 3, 5],
[1, 4, 7, 6] );
The above code uses ES6 rest parameters to access all the arrays passed as arguments. Then using the concat() function, I am joining all the individual arrays to a single array. Finally, filter function has been used to identify and return the unique items from this array. The logic here is to find out the first index of the current item and if there are no more occurrence from the first index then we return that item.