How to find diff between array and array of arrays - javascript

x = [1, 2,3, 5]; y = [1, [2], [3, [[4]]],[5,6]]));
I have to find the difference between these 2 arrays.
function arr_diff (a1, a2) {
var a = [], diff = [];
for (var i = 0; i < a1.length; i++) {
a[a1[i]] = true;
}
for (var i = 0; i < a2.length; i++) {
if (a[a2[i]]) {
delete a[a2[i]];
} else {
a[a2[i]] = true;
}
}
for (var k in a) {
diff.push(k);
}
return diff;
};
This is what I tried but since it has array of arrays, this not working for me.
Can anyone please suggest help.

You could just flatten the arrays before you find the difference
function arr_diff(a1, a2) {
a1 = a1.toString().split(',');
a2 = a2.toString().split(',');
if (a1.length < a2.length) {var t = a1; a1 = a2; a2 = t};
return a1.filter( x => (!a2.includes(x)) ).map(Number);
}
var x = [1, 2,3, 5];
var y = [1, [2], [3, [[4]]],[5,6]];
var r = arr_diff(x,y);
console.log(r);

You definitely need to flatten all the arrays you want to compare using a function found here.
After flattening them, you can compare them using a function found here
let x = [1, 2,3, 5];
let y = [1, [2], [3, [[4]], [5,6] ]]
const flatten = list => list.reduce(
(a, b) => a.concat(Array.isArray(b) ? flatten(b) : b), []
)
const difference = (arr1,arr2) => {
arr1 = flatten(arr1)
arr2 = flatten(arr2)
return arr1.filter(e => arr2.indexOf(e) === -1)
.concat(arr2.filter(e => arr1.indexOf(e) === -1))
}
console.log(difference(x,y)) // [4,6]

Related

How to create nested array of different length from a multidimensional array

I have an array that looks like this:
arr = [[1,2,3],
[4,5,6],
[7,8,9]]
I have initialized an empty array and I want put the diagonals of the arr inside the new array. So i've tried this:
arr = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9]
]
new_arr = [];
tail = arr.length - 1;
for (let i = 0; i < arr.length; i++) {
for (let j = 0; j < arr[i].length; j++) {
if (j == i) {
new_arr.push(arr[i][j]);
}
if (j == tail) {
new_arr.push(arr[i][j]);
tail--;
}
}
}
console.log(new_arr)
The logic seems to work but I can't seem to get the structure right. What I want is to nest two arrays inside the new array like this:
[[1,5,9],[3,5,7]]
But what I get is one array with the right values unordered. How to get the expected output? Any help is appreciated. Thanks!
You need to have 2 separate temporary arrays. And you don't need nested loops. You can optimize the code like this with a single loop if you understand the math.
arr = [[1,2,3],
[4,5,6],
[7,8,9]];
function findDiagonals(arr) {
const diagonal_1 = [];
const diagonal_2 = [];
for( let i = 0; i < arr.length; i++ ) {
diagonal_1.push(arr[i][i]);
diagonal_2.push(arr[i][arr.length - (i+1)]);
}
return [diagonal_1, diagonal_2];
}
console.log(findDiagonals(arr));
var arr = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9]
];
var diagonal1 = [];
var diagonal2 = [];
for (var i = 0; i < arr.length; i++) {
diagonal1.push(arr[i][i]);
diagonal2.push(arr[i][arr.length - i - 1]);
}
var new_arr = [diagonal1, diagonal2];
console.log(new_arr)
The following solution would work for you if the width and height of the number matrix is always equal.
const arr = [[1,2,3],
[4,5,6],
[7,8,9]];
const result = [[],[]];
arr.map((row,index) => {
result[0].push(row[0+index]);
result[1].push(row[row.length - index - 1]);
});
console.log(result); // [[1,5,9],[3,5,7]]
This is a O(n) approach by using the function Array.prototype.reduce.
const arr = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9]
];
const result = arr.reduce(([left, right], array, row, {length}) => {
return [[...left, array[row]], [...right, array[length - row - 1]]];
}, [[],[]]);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
the difficulty is low:
const
arr = [[1,2,3],[4,5,6],[7,8,9]]
, new_arr = [[],[]]
;
let p0 = 0, p1 = arr.length
for( let inArr of arr)
{
new_arr[0].push( inArr[p0++] )
new_arr[1].push( inArr[--p1] )
}
console.log( JSON.stringify( new_arr ))
in a one Line code:
const
arr = [[1,2,3],[4,5,6],[7,8,9]]
, new_arr = arr.reduce(([lft,rgt],A,i,{length:Sz})=>([[...lft,A[i]],[...rgt,A[Sz-i-1]]]),[[],[]])
;
console.log( JSON.stringify( new_arr )) // [[1,5,9],[3,5,7]]

Javascript Smallest Number in 3 Arrays

I can figure out iterating through an array for similar numbers, but creating a function in order to do so through 3 arrays is stumping me for some reason. For the assignment I need to limit my built in functions to indexOf and .length.
For example:
var sample = [1,2,3,5,6], [2,3,4,5,6], [4,5,6,7,8]
function smallestCommonNumber(arr1, arr2, arr3){
}
I will need this function to iterate through the three ascending arrays and return the smallest of any pairs (must match all 3 arrays) and if not, return false. I know that using indexOf will return a specified item, but how would I use that for an unspecified array?
Assuming the arrays are sorted with ascending values as specified in the question.
Iterate each number in one of the arrays and check if it exists in both of the other arrays using indexOf, if not found it will return -1, here using ~ operator to shift -1 to 0 to get a falsy value.
Could just as well just check .indexOf(..) > -1.
function smallestCommonNumber(arr1, arr2, arr3){
for (const number of arr1) {
if (~arr2.indexOf(number) && ~arr3.indexOf(number)) {
return number;
}
}
return false;
}
console.log(smallestCommonNumber([1,2,3,5,6], [2,3,4,5,6], [4,5,6,7,8]));
For a version that finds the smallest number without ascending arrays:
function smallestCommonNumber(arr1, arr2, arr3){
let smallest = null;
for (const number of arr1) {
if (~arr2.indexOf(number) && ~arr3.indexOf(number)) {
smallest = number < smallest ? number : smallest ?? number;
}
}
return smallest ?? false;
}
console.log(smallestCommonNumber([6,5,3,2,1], [2,3,4,5,6], [4,5,6,7,8]));
If the 3 arrays are sorted in ascending order you can iterate over all 3 arrays from left to right using 3 pointers until you get a number that occurs in all 3 arrays, and just return that number since that will be guaranteed to be the smallest:
function smallestCommonNumber(arr1, arr2, arr3) {
let i = 0,
j = 0,
k = 0;
while (i < arr1.length && j < arr2.length && k < arr3.length) {
if (arr1[i] === arr2[j] && arr2[j] === arr3[k]) {
return arr1[i];
} else if (arr1[i] < arr2[j]) {
i++;
} else if (arr2[j] < arr3[k]) {
j++;
} else {
k++;
}
}
return false;
}
const a1 = [1, 2, 3, 5, 6];
const a2 = [2, 3, 4, 5, 6];
const a3 = [4, 5, 6, 7, 8];
// Assumes a1, a2, and a3 are sorted in ascending order
console.log(smallestCommonNumber(a1, a2, a3));
As requested by #kinduser in the comments here is a solution that works with unsorted arrays as well:
function smallestCommonNumber(arr1, arr2, arr3) {
const set1 = new Set(arr1);
const set2 = new Set(arr2);
const intersection1 = new Set([...set1].filter(n => set2.has(n)));
if (!intersection1.size) {
return false;
}
const set3 = new Set(arr3);
const intersection2 = new Set([...intersection1].filter(n => set3.has(n)));
return intersection2.size ? Math.min(...intersection2) : false;
}
const a1 = [1, 2, 3, 5, 6];
const a2 = [2, 5, 4, 3, 6];
const a3 = [4, 5, 6, 7, 8];
console.log(smallestCommonNumber(a1, a2, a3));
var sample1 = [1,2,3,5,6]
var sample2 = [2,3,4,5,6]
var sample3 = [4,5,6,7,8]
function smallestCommonNumber(...arrays){
const smallestsOfAllArrays = []
arrays.forEach(array => {
smallestsOfAllArrays.push(smallestOfOneArray(array))
})
return smallestOfOneArray(smallestsOfAllArrays)
}
function smallestOfOneArray(oneArray){
return oneArray.reduce((acm, value) => acm <= value ? acm : value)
}
console.log(smallestCommonNumber(sample1, sample2, sample3))
//1
Do like:
function inArray(value, array){
if(array.indexOf(value) === -1){
return false;
}
return true;
}
function least(){
let a = [...arguments], l = a.length, q = l-1, r = [];
for(let i=0,b; i<l; i++){
b = a[i];
for(let n=0,c,h; n<l; n++){
if(i !== n){
c = a[n]; h = [];
for(let v of c){
if(inArray(v, b))h.push(v);
}
if(h.length === q)r.push(...h);
}
}
}
return Math.min(...r);
}
const sample1 = [6,3,1,5,2], sample2 = [2,3,4,5,6], sample3 = [4,5,6,7,8];
console.log(least(sample1, sample2, sample3));

Add pattern to an array without push()

Is there a way to code this without using any methods?
a is an array, n is the number of times the pattern is repeated in the new array
const func = (a, n) => {
const arr = [];
for (let i = 0; i < n; i++) {
arr.push(...a);
}
console.log(arr);
};
func([1, 2, 3, 4], 2);
You could take a separate index and assign the values.
const func = (a, n) => {
let array = [],
i = 0;
while (n--) for (const v of a) array[i++] = v;
return array;
};
console.log(...func([1, 2, 3, 4], 2));
Well, you could use two loops and directly assign ith array item.
const func = (a, n) => {
const arr = [];
for (let i = 0; i < n; i++) {
for (let j = 0; j < a.length; j++) {
arr[i * a.length + j] = a[j]
}
}
console.log(arr);
};
func([1, 2, 3, 4], 2);
that ?
const func=(a, n)=>
{
const arr = []
let p = 0
for (let i=0;i<n;++i) for(let v of a) arr[p++] = v
console.log(JSON.stringify(arr));
}
func([1, 2, 3, 4], 2);
You could use the spread operator to create a new array for each iteration of the loop. This would mean that your arr variable can't be a constant though since it gets overwritten with a new array.
const func = (a, n) => {
let arr = [];
for (let i = 0; i < n; i++) {
arr = [...arr, ...a];
}
console.log(arr);
};
func([1, 2, 3, 4], 2);

JS - Sum Of Two Arrays where arrays can be of unequal length

I need function like this.
function sum(arr1, arr2) {
return totalArray
};
sum([1,2,3,4], [5,6,7,8,9]) // [6,8,10,12,9]
I tried it this way:
var array1 = [1, 2, 3, 4];
var array2 = [5, 6, 7, 8, 100];
var sum = array1.map((num, idx) => num + array2[idx]); // [6,8,10,12]
First you can get an array out of the function's arguments using Spread syntax (...), then sort it by array's length using Array.prototype.sort() and finally Array.prototype.reduce() to get the result array
Code:
const sum =(...arrays) => arrays
.sort((a, b) => b.length - a.length)
.reduce((a, c) => a.map((n, i) => n + (c[i] || 0)) || c)
// two arrays
const resultTwoArrays = sum([1, 2, 3, 4], [5, 6, 7, 8, 9])
console.log(resultTwoArrays) // [6, 8, 10, 12, 9]
// three arrays or more...
const resultThreeArrays = sum([1, 2, 3, 4], [5, 6, 7, 8, 9], [1, 2])
console.log(resultThreeArrays) // [7, 10, 10, 12, 9]
.as-console-wrapper { max-height: 100% !important; top: 0; }
At the risk of being unpopular due to using a loop:
function sum(arr1, arr2) {
let totalArray = [];
const totalLength = Math.max(arr1.length, arr2.length);
for (let i = 0; i < totalLength; i++) {
totalArray[i] = (arr1[i] || 0) + (arr2[i] || 0);
}
return totalArray;
}
The || 0 handles the possibility the array doesn't have an entry at i, because if it doesn't, the result of arrX[i] is undefined, and undefined || 0 is 0.
I try this way.
var array1 = [1, 2, 3, 4];
var array2 = [5, 6, 7, 8, 100];
var sum = array1.map((num, idx) => num + array2[idx]); // [6,8,10,12]
Very close, but map will stop at the end of array1, so you won't get the subsequent entries from array2. Just pick the longer of the two arrays, then handle the fact that the other array may not have an entry at arrayX[idx]. You can do that with the || 0 idiom:
function sum(array1, array2) {
var a, b;
if (array1.length > array2.length) {
a = array1;
b = array2;
} else {
a = array2;
b = array1;
}
return a.map((num, idx) => num + (b[idx] || 0));
}
console.log(sum([1, 2, 3, 4], [5, 6, 7, 8, 100]));
Alternately, you can use the new (but polyfill-able) Array.from to create the result array and use the callback to build the entries:
function sum(array1, array2) {
return Array.from(
{length: Math.max(array1.length, array2.length)},
(_, i) => (array1[i] || 0) + (array2[i] || 0)
);
}
console.log(sum([1, 2, 3, 4], [5, 6, 7, 8, 100]));
Mosho's answer is wonderfully simple, though.
Find the long and short array according to length. Iterate the short array with Array.map(), and take the value from the long array. Then add the leftovers from the long array using Array.slice(), and Array.concat():
function sum(arr1, arr2) {
const [l, s] = arr1.length >= arr2.length ? [arr1, arr2] : [arr2, arr1];
return s.map((n, i) => n + l[i])
.concat(l.slice(s.length));
};
console.log(sum([1,2,3,4], [5,6,7,8,9]));
Are we code golfing this? Here's a generator solution.
const summer = function*(a, b, i=0) {
while(i < a.length || i < b.length) yield (a[i] || 0) + (b[i++] || 0);
};
const sum = (a, b) => [...summer(a,b)];
console.log(sum([1,2,3,4], [5,6,7,8,9])) // [6,8,10,12,9]
You can have a custom logic something like this:
function sum(arr1, arr2) {
var length, selectedArray, nonSelectedArray;
if(arr1.length>arr2.length){
length = arr1.length;
selectedArray = arr2;
nonSelectedArray = arr1;
}else {
length = arr2.length;
selectedArray = arr1;
nonSelectedArray = arr2;
}
var totalArray = [];
for(var i=0; i<length; i++){
if(selectedArray[i]){
totalArray.push(selectedArray[i] + nonSelectedArray[i]);
} else {
totalArray.push(nonSelectedArray[i]);
}
}
return totalArray
};
var res = sum([1,2,3,4], [5,6,7,8,9]);
console.log(res);
Try with map():
function sum(arr1, arr2) {
var [a1, a2] = arr1.length > arr2.length ? [arr1, arr2] : [arr2, arr1]
var totalArray = a1.map(function(i, idx){
i = (i + a2[idx] || i + 0);
return i;
})
return totalArray;
};
console.log(sum([1,2,3,4], [5,6,7,8,9])) // [6,8,10,12,9]

javascript remove array from array

Assume we have the following arrays:
a = [1, 2, 3, 4, 5]
and
b = [2, 3]
How can I subtract b from a? So that we have c = a - b which should be equal to [1, 4, 5]. jQuery solution would also be fine.
Assuming you're on a browser that has Array.prototype.filter and Array.prototype.indexOf, you could use this:
var c = a.filter(function(item) {
return b.indexOf(item) === -1;
});
If the browser in question does not have those methods, you may be able to shim them.
This is a modified version of the answer posted by #icktoofay.
In ES6 we can make use of:
Array.prototype.contains()
Array.prototype.filter()
Arrow functions
This will simplify our code to:
var c = a.filter(x => !b.includes(x));
Demo:
var a = [1, 2, 3, 4, 5];
var b = [2, 3];
var c = a.filter(x => !b.includes(x));
console.log(c);
For code that would work in all browsers, you would have to manually find each element from b in a and remove it.
var a = [1, 2, 3, 4, 5];
var b = [2, 3];
var result = [], found;
for (var i = 0; i < a.length; i++) {
found = false;
// find a[i] in b
for (var j = 0; j < b.length; j++) {
if (a[i] == b[j]) {
found = true;
break;
}
}
if (!found) {
result.push(a[i]);
}
}
// The array result now contains just the items from a that are not in b
Working example here: http://jsfiddle.net/jfriend00/xkBzR/
And, here's a version that could be faster for large arrays because it puts everything into an object for hashed lookups rather than brute force array searching:
var a = [1, 2, 3, 4, 5];
var b = [2, 3];
function filterArray(src, filt) {
var temp = {}, i, result = [];
// load contents of filt into object keys for faster lookup
for (i = 0; i < filt.length; i++) {
temp[filt[i]] = true;
}
// go through src
for (i = 0; i < src.length; i++) {
if (!(src[i] in temp)) {
result.push(src[i]);
}
}
return(result);
}
var filtered = filterArray(a, b);
Working example here: http://jsfiddle.net/jfriend00/LUcx6/
For the ones struggling with Objects, like Date, you'll find out that two different objects are never equal to each other, even if they have the same values, so the answers above wouldn't work.
Here is an answer to this problem in ES6.
const c = a.filter(aObject => b.findIndex(bObject => aObject.valueOf() === bObject.valueOf()) === -1)
Here an implementation for try works in all browsers:
if('filter' in Array == false) {
Array.prototype.filter =
function(callback) {
if(null == this || void 0 == this) {
return;
}
var filtered = [];
for(i = 0, len = this.length; i < len; i++) {
var tmp = this[i];
if(callback(tmp)) {
filtered.push(tmp);
}
}
return filtered;
}
}
a = [1, 2, 3, 4, 5];
b = [2, 3];
var c = a.filter(function(item) { /*implementation of icktoofay */
return b.indexOf(item) === -1;
});
Might be an outdated query but i thought this might be useful to someone.
let first = [1,2,3,4,5,6,7,9];
let second = [2,4,6,8];
const difference = first.filter(item=>!second.includes(item));
console.log(difference);//[ 1, 3, 6,7]
/*
the above will not work for objects with properties
This might do the trick
*/
const firstObj = [{a:1,b:2},{a:3,b:4},{a:5,b:6},{a:7,b:8}]//not ideal. I know
const secondObj = [{a:3,b:4},{a:7,b:8}]
const objDiff = firstObj.filter(obj=>
!secondObj.find(sec=>//take note of the "!"
sec.a===obj.a
&&//or use || if you want to check for either or
sec.b===obj.b
)//this is formatted so that it is easily readable
);
console.log(objDiff)/*
[
{
"a": 1,
"b": 2
},
{
"a": 5,
"b": 6
}
]
*/

Categories

Resources