Find elements in an array not contained in another array of objects - javascript

I have an array arr1 = [1,2,3,4,5]
There is another array of objects arr2 = [{'id':2, 'name':'A'},{'id':4, 'name':'B'}]
I am looking for find elements in arr1 which are not in arr2. The expected output is [1,3,5]
I tried the following but it doesn't work.
const arr = arr1.filter(i => arr2.includes(i.id));
Can you please help?

A solution with O(arr2.length) + O(arr1.length) complexity in Vanilla JS
var arr1= [1,2,3,4,5];
var arr2 = [{'id':2, 'name':'A'},{'id':4, 'name':'B'}];
var tmp = arr2.reduce(function (acc, obj) {
acc[obj['id']] = true;
return acc;
}, {});
var result = arr1.filter(function(nr) {
return !tmp.hasOwnProperty(nr);
})

arr2 is an array of objects, so arr2.includes(i.id) doesn't work because i (an item from arr1) is a number, which doesn't have an id property, and because arr2 is an array of objects.
Turn arr2's ids into a Set first, then check whether the set contains the item being iterated over:
const arr1 = [1,2,3,4,5];
const arr2 = [{'id':2, 'name':'A'},{'id':4, 'name':'B'}];
const ids = new Set(arr2.map(({ id }) => id));
const filtered = arr1.filter(num => !ids.has(num));
console.log(filtered);

You can try with Array.prototype.some():
The some() method tests whether at least one element in the array passes the test implemented by the provided function. It returns a Boolean value.
const arr1 = [1,2,3,4,5]
const arr2 = [{'id':2, 'name':'A'},{'id':4, 'name':'B'}]
const arr = arr1.filter(i => !arr2.some(j => j.id == i));
console.log(arr);

We can use the filter method like below to check the condition required
var arr1 = [1, 2, 3, 4, 5]
var arr2 = [{ 'id': 2, 'name': 'A' }, { 'id': 4, 'name': 'B' }]
var ids = [];
arr2.forEach(element => {
ids.push(element['id'])
});
var result = arr1.filter(s => ids.indexOf(s) < 0)
console.log(result)

let arr1= [1,2,3,4,5];
let arr2 = [{'id':2, 'name':'A'},{'id':4, 'name':'B'}]
let arr2Ids=arr2.map(item=>item.id);
let result=arr1.filter(n => !arr2Ids.includes(n));

You can use find on arr2 instead of includes since arr2 is composed of object
const arr = arr1.filter(i => !arr2.find(e => e.id===i));

Related

How to create a nested while loop based on N number of arrays?

I'm trying to create a combination of all possible variants of the arrays given below, which are pretty self-explanatory.
let arr1 = ['Small', 'Medium', 'Large', 'Extra-Large']
let arr2 = ['Black','Red','White']
let arr3 = ['Normal','Limited-Edition']
let combos = []
arr1.forEach((i) => {
arr2.forEach((j) => {
arr3.forEach((k) => {
combos.push(i + '-' + j + '-' + k)
})
})
})
console.log(combos)
This gives the output I want, however I want to create a function that takes an arbitrary array of arrays, [arr1, arr2, arr3.....arrN] and creates a nested loop of each of them, and returns a combined value of strings.
How do I go around creating such a function?
You can use something like this using reduce. I referenced this post
let arr1 = ['Small', 'Medium', 'Large', 'Extra-Large']
let arr2 = ['Black','Red','White']
let arr3 = ['Normal','Limited-Edition']
let arr4 = ['x','y','z']
let arr = [arr1,arr2,arr3,arr4]
let combined = arr.reduce((a,c)=>{
return a.flatMap(x=>c.map(y=>x.concat(y)))
},[[]]).map((z) => z.join("-"))
console.log(combined)
console.log(combined.length) //4*3*2*3 = 72
UPDATE - This one is taken directly from the top answer with a very small modification
let arr1 = ['Small', 'Medium', 'Large', 'Extra-Large']
let arr2 = ['Black','Red','White']
let arr3 = ['Normal','Limited-Edition']
let arr4 = ['x','y','z']
let arr = [arr1,arr2,arr3,arr4]
const cartesian =
(a) => a.reduce((a, b) => a.flatMap(d => b.map(e => [d, e].flat()))).map(x=>x.join("-"));
console.log(cartesian(arr))
const arr1 = ['Small', 'Medium', 'Large', 'Extra-Large']
const arr2 = ['Black','Red','White']
const arr3 = ['Normal','Limited-Edition']
const arr4 = ['x','y','z']
const arr = [arr1,arr2,arr3,arr4]
const merged = [].concat.apply([], arr);
console.log(merged);

How to group by two array by index in javascript with es6 or lodash?

We have same two arrays to groupby theme by index.
Two arrays with same length and different value like blow.
How to groupby two array with their index by ES6 reduce or lodash?
array1 = [1,2,3,4] OR [{a:1},{b:2},{c:3},{d:4}]
array2 = [5,6,7,8] OR [{e:5},{f:6},{g:7},{h:8}]
finalArray = [[1,5],[2,6],[3,7],[4,8]]
I'm trying with different ways like group by with reduce in es6 or lodash concat but i can't find best solution for my problems.
Try this:
let array1 = [1, 2, 3, 4];
let array2 = [5, 6, 7, 8];
let res = array1.map((value, index) => {
return [value, array2[index]]
})
console.log(res);
If it is array of objects
let array1 = [{a:1},{b:2},{c:3},{d:4}];
let array2 = [{e:5},{f:6},{g:7},{h:8}];
let res = array1.map((value, index) => {
return [Object.values(value)[0],Object.values(array2[index])[0]]
})
console.log(res)
Use lodashes zip function
// _ is lodash
const array1 = [1,2,3,4]
const array2 = [5,6,7,8]
console.log(_.zip(array1, array2))
result
[ [ 1, 5 ], [ 2, 6 ], [ 3, 7 ], [ 4, 8 ] ]
If you are working with the array of objects. Get just the values using Object.values and grab the 0th element.
const array3 = [{a:1},{b:2},{c:3},{d:4}];
const array4 = [{e:5},{f:6},{g:7},{h:8}];
function firstval(ob){
return Object.values(ob)[0]
}
console.log(_.zip(array3.map(firstval), array4.map(firstval)))
You can also write your own zip. This is a limited version. That handles only 2 elements, doesn't accept or return generators etc.
It could easily be extended to take a spread operator and therefore any number of arguments. You don't seem to need that level of flexibility though.
function zip(a, b) {
const num = Math.min(a.length, b.length);
const result = [];
for(i = 0; i < num; i++) result.push([a[i], b[i]]);
return result;
}
Following code works under these assumptions:
all input arrays have same length
if array element is object, it has only one property
function getValue(element) {
if (typeof element === 'object') {
return Object.values(element).pop()
} else {
return element
}
}
function zipArrays(arr1, arr2) {
return arr1.reduce((acc, elm1, index) => {
const elm2 = arr2[index]
const elm = [getValue(elm1), getValue(elm2)]
acc.push(elm)
return acc
}, [])
}
// usage:
const array1 = [1,2,3,4] // OR [{a:1},{b:2},{c:3},{d:4}]
const array2 = [5,6,7,8] // OR [{e:5},{f:6},{g:7},{h:8}]
const finalArray = zipArrays(array1, array2)

How use reduce() to concat an array and delete the items duplicated

I have a problem using the reduce function in JavaScript. My goal is to take an array of arrays and, using reduce, then concat all the values and delete the duplicates:
I have an array like this:
firstArray = [[1, 2],[2, 3, 4],[4, 5, 6]]
I need an array like this after apply reduce():
resultArray = [1, 2, 3, 4, 5, 6]
const arrayElements = [[1,2],[2,3,4],[5,6]];
const newArray = arrayElements.reduce((total, value) => {
return total.concat(value);
}, []);
This is the fragment that I have, this only concat all the values, this is to say, [1, 2, 2, 3, 4, 5, 6]
var num = [[1,2],[2,3,4],[5,6]];
var unique_numbers = [].concat(...num);
unique_numbers = Array.from(new Set(unique_numbers ));
You can use Set and flat
const array = [[1,2],[2,3,4],[5,6]];
const newArray = [...new Set(array.flat(Infinity))]
console.log(newArray)
Your reduce is correct, just add the data to a set, and convert the set to an array using spread syntax ...
const arrayElements = [[1,2],[2,3,4],[5,6]];
const newArray = [...new Set(arrayElements.reduce((total, value) => total.concat(value), []))];
console.log(newArray)
You can do this using Set:
const newArray = arrayElements.reduce((accum, arr) => [...accum, ..arr], [])
const arrNoDupes = [...new Set(newArray)]
or using filter:
const newArray = arrayElements.reduce((accum, arr) => [
...accum
...arr.filter(value => !accum.includes(value))
], [])
These are just two ways you can do what you want to achieve.
Here is the old fashioned ES5 way in case browser support is a concern.
var arrayElements = [[1,2],[2,3,4],[5,6]];
var newArray = arrayElements.reduce(function(total, value){
return total.concat(value).filter(function (x, i, a) {
return a.indexOf(x) == i;
});
}, []);
console.log(newArray)

How do you merge the item values from 2 separate arrays in javascript?

I'm not looking to push the values from one array into another, or concatenate them but simply sum the item values from each - either into a new array, or alternatively amending either arrayOne or arrayTwo with the values from the other e.g.
var arrayOne = [1,2,3,4,5]
var arrayTwo = [2,4,6,8,10]
// loop / function..
var newArray = [3,6,9,12,15]
OR arrayOne = [3,6,9,12,15]
I thought this would be straightforward but this requires 2 loops running at the same time?
Thanks for your help!
var arrayOne = [1,2,3,4,5];
var arrayTwo = [2,4,6,8,10];
var newArray = [];
newArray = arr1.map((item,index)=>{
return item + arr2[index]
});
You could collect all wanted array for adding values at the same index in an array and reduce the arrays.
This works with an arbitrary count of arrays.
var array1 = [1, 2, 3, 4, 5],
array2 = [2, 4, 6, 8, 10],
result = [array1, array2].reduce(
(a, b) => (b.forEach((v, i) => a[i] = (a[i] || 0) + v), a)
);
console.log(result);
You can use Array's map():
var arrayOne = [1,2,3,4,5];
var arrayTwo = [2,4,6,8,10];
var newArray = arrayOne.map( (item, i) => item += arrayTwo[i] );
console.log(newArray);

How do I find the number of common numbers occurring in 2nd array?

commonCount(ar1, ar2)
if arr1 = [1,1,2,3,3] and arr2 = [1,4,3,1,1], the answer is 3
My thought process:
initialize accumulator
iterate through arr1
if arr1[i] is in the arr2, add 1 to the accumulator
remove the arr1[i] from arr2 (because don't want to have duplicate if the number already exist)
return accumulator
1) How do I check if arr1[i] is in the arr2?
2) How do I remove arr1[i] from arr2?
console.log([1,2,3,4,5].filter((n) => [1,1,2,10,11].includes(n)))
This is the code to calculate the intersection.
to filter them out you will do this
console.log([1,1,2,10,11].filter((n) => ![1,2,3,4,5].includes(n)))
To remove an element x from an array arr we can do this
var array = [1,2,3];
var index = array.indexOf(3);
if( index >= 0)
array.splice(index,1);
Removing an element also answers your question on how to check if the elements exist in the array.
try with arr2 .filter(val => !arr1.includes(val)); to remove duplicate value from second array
var arr1 = [1, 1, 2, 3, 3];
var arr2 = [1, 4, 3, 1, 1];
arr2 = arr2 .filter(val => !arr1.includes(val));
console.log(arr1);
console.log(arr2);
You can store all unique values along with its frequency in an object using array#reduce and then filter result by looking into unique object using array#filter and decrementing the frequency once you find the same value. After that simply return length.
const arr1 = [1,1,2,3,3],
arr2 = [1,4,3,1,1];
var commonCount = (ar1, ar2) => {
const uniques = ar1.reduce((res, v) => {
res[v] = (res[v] || 0) + 1;
return res;
},{});
const common = arr2.filter(v => uniques[v] > 0 && uniques[v]--);
return common.length;
}
console.log(commonCount(arr1,arr2));

Categories

Resources