Related
I need loop thought two array and return another array with different values.
Example of two arrays:
let arr1 = ['one' , 'two' , 'three'];
let arr2 = ['four' , 'one' , 'two'];
What do I need?
Loop thought both array and return the same value, I expect new array like:
let res = [
{ name : 'one' , isSame: true },
{ name : 'two' , isSame: true },
{ name : 'three' },
{ name : 'four' }
];
I am removed the duplicate items and add isSame value to true on duplicated values.
One and two are duplicated ( twice ).
What I have tried
let arr3 = arr1.map((item, i) =>
Object.assign({}, item, arr2[i])
);
But I got a splitted array and it's removed duplicated
Reduce to an intermediate object and then map that object's entries:
const arr1 = ['one' , 'two' , 'three'];
const arr2 = ['four' , 'one' , 'two'];
const result = Object.entries([...arr1, ...arr2].reduce(
(a, v) => ({ ...a, [v]: v in a }),
{}
)).map(([name, isSame]) => ({ name, isSame }));
console.log(result);
The spreading behavior in the reduce() callback increases time complexity in favor of being more terse, but can easily be avoided, making this solution O(n):
const arr1 = ['one' , 'two' , 'three'];
const arr2 = ['four' , 'one' , 'two'];
const result = Object.entries([...arr1, ...arr2].reduce(
(a, v) => {
a[v] = v in a;
return a;
},
{}
)).map(([name, isSame]) => ({ name, isSame }));
console.log(result);
I would suggest you to use reduce() to do it
let arr1 = ['one' , 'two' , 'three'];
let arr2 = ['four' , 'one' , 'two'];
let arr3 = arr1.concat(arr2)
let result = arr3.reduce((a,c) =>{
let obj = a.find(i => i.name == c)
if(obj){
obj['isSame'] = true
}else{
a.push({'name':c})
}
return a
},[])
console.log(result)
Update:
solution without reduce(),using set() to remove duplicate elements,and using includes() to find duplicate elements
let arr1 = ['one' , 'two' , 'three'];
let arr2 = ['four' , 'one' , 'two'];
let arr3 = [...new Set(arr1.concat(arr2))]
let result = arr3.map(a =>{
let data = {'name':a}
if(arr1.includes(a) && arr2.includes(a)){
data["isSame"] = true
}
return data
})
console.log(result)
Update: Based on OP's comments,show with opposite result
let arr1 = ['one' , 'two' , 'three'];
let arr2 = ['four' , 'one' , 'two'];
let arr3 = [...new Set(arr1.concat(arr2))]
let result = arr3.map(a =>{
let data = {'name':a}
if(!arr1.includes(a) || !arr2.includes(a)){
data["isSame"] = true
}
return data
})
console.log(result)
Since you don't want reduce, you can loop through each item, and check the next few values.
This is natively faster with less function calls, just two for loops.
let arr1 = ['one', 'two', 'three'];
let arr2 = ['four', 'one', 'two'];
console.log(merge(arr1, arr2));
function merge(a, b) {
const merged = a.concat(b); // combine arrays
const result = [];
let stop = merged.length; // create a variable for when to stop
for(let i = 0; i < stop; i++) {
const current = merged[i];
let same = false;
// look through the rest of the array for indexes
for(let t = i + 1; t < stop; t++) {
if(current === merged[t]) {
same = true;
merged.splice(t, 1); // remove duplicate elements from the array so we don't come across it again
stop--; // we've removed an element from the array, so we have to stop 1 earlier
// we don't break this loop because there may be more than 2 occurences
}
}
const out = { name: current };
if(same) out.isSame = true;
result.push(out);
}
return result;
}
I have used map() function of array.
map() returns new array by performing code logic on each valid entry.
[...new Set([...arr1, ...arr2])], this will return new array with unique values.
I am assuming, that you are checking if value is in both array or not and based upon that we are returning object.
let arr1 = ['one', 'two', 'three'];
let arr2 = ['four', 'one', 'two'];
let mergedArray = [...new Set([...arr1, ...arr2])];
let result = mergedArray.map(value => {
if (arr1.includes(value) && arr2.includes(value)) {
return {
value,
isInBothArray: true
}
} else {
return {
value,
isInBothArray: false
}
}
});
console.log(result);
const arr1 = ['one' , 'two' , 'three'];
const arr2 = ['four' , 'one' , 'two'];
// returns the duplicate values in the two arrays
const findDuplicates = (arr) => {
let sorted_arr = arr.slice().sort();
let results = [];
for (let i = 0; i < sorted_arr.length - 1; i++) {
if (sorted_arr[i + 1] == sorted_arr[i]) {
results.push(sorted_arr[i]);
}
}
return results;
}
let values = ([...new Set([...arr1, ...arr2])]);
let duplicates = findDuplicates(values);
let retval = [];
for(let i = 0; i < values.length; i++) {
let isSame = duplicates.includes(values[i]);
retval.push({name: values[i], isSame: isSame})
}
const arr1 = ['one', 'two', 'three'];
const arr2 = ['four', 'one', 'two'];
const result = Array.from(new Set(arr1.concat(arr2))).reduce((p, c) => {
const obj = { name: c };
if (arr1.concat(arr2).join("").split(c).length - 1 > 1) obj.isSame = true;
p.push(obj)
return p;
}, []);
console.log(result);
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));
I am using javascript to compare a single array and a multidimensional array.
Here i want to compare those 2 array and the matched value should be shown.
arr[1,2,3] value to be searched in multidimensional array " md2 ".
This is my Code :: i have taken an single array and other as multidimensional array
var arr = [1,2,3];
var md2 = [[23,8,2],[1,5,8],[1,2,3],[8,5,2]];
for(var j=0; j<md2.length ; j++){
if(arr == md2[j]){
console.log(arr + " ... " + md2[j]);
}
}
Required O/P :- [1,2,3] should match and should be displayed in the console
You can use .find() and .every() methods to find array inside multi-dimensional array:
var arr1 = [1,2,3];
var arr2 = [1,2,5];
var md2 = [[23,8,2],[1,5,8],[1,2,3],[8,5,2]];
var searchAndPrint = (a1, a2) => {
let arr = a1.find(a => a.every((v, i) => v === a2[i]));
if(arr)
console.log(arr);
else
console.log("No Results");
};
searchAndPrint(md2, arr1);
searchAndPrint(md2, arr2);
You can't compare arrays in js. If you wanna compare simple arrays you can convert them to string to compare. This method is not applicable to array containing objects.
var arr = [1,2,3];
var md2 = [[23,8,2],[1,5,8],[1,2,3],[8,5,2]];
for(var j=0; j<md2.length ; j++){
if(arr.toString() === md2[j].toString()){
console.log(arr + " ... " + md2[j]);
}
}
You can use JSON.stringify to compare the arrays.
var arr = [1,2,3];
var md2 = [[23,8,2],[1,5,8],[1,2,3],[8,5,2]];
for(var j=0; j<md2.length ; j++){
if(JSON.stringify(arr) === JSON.stringify(md2[j])){
console.log(arr + " ... " + md2[j]);
}
}
For checking, you need to check the length and the items directly, because you have no same object reference.
var arr = [1, 2, 3],
md2 = [[23, 8, 2], [1, 5, 8], [1, 2, 3], [8, 5, 2]];
console.log(md2.some(a => arr.length === a.length && a.every((v, i) => v === arr[i])));
I want concat following two arrays by removing duplicates without assigning to third variable:
var arr1=[{id:1,name:'AB'},{id:2,name:'CD'}];
var arr2=[{id:3,name:'EF'},{id:2,name:'CD'}];
I want arr1 like:
[{id:1,name:'AB'},{id:2,name:'CD'},{id:3,name:'EF'}]
arr1.concat(arr2);
First merge two arrays then put array into a map with their ids. Then create array from map values.
var arr1=[{id:1,name:'AB'},{id:2,name:'CD'}];
var arr2=[{id:3,name:'EF'},{id:2,name:'CD'}];
arr1 = arr1.concat(arr2) // merge two arrays
let foo = new Map();
for(const tag of arr1) {
foo.set(tag.id, tag);
}
let final = [...foo.values()]
console.log(final)
Can use Array reduce and findIndex to achieve what you want.
var arr1=[{id:1,name:'AB'},{id:2,name:'CD'}];
var arr2=[{id:3,name:'EF'},{id:2,name:'CD'}];
// loop over arr2, add the elements of array2 if it doesn't exist in array1
var newArr = arr2.reduce((acc, eachArr2Elem) => {
if (arr1.findIndex((eachArr1Elem) => eachArr1Elem.id === eachArr2Elem.id && eachArr1Elem.name === eachArr2Elem.name) === -1) {
acc.push(eachArr2Elem)
}
return acc
}, [...arr1]); // initialize the new Array with the contents of array1
console.log(newArr)
using the spread operator you can flatten any amount of arrays passed to the combineAndDeDup method, i have also split out some logic methods for (hopefully) more readable code. i hope this helps.
const arr1 = [{id:1,name:'AB'}, {id:2,name:'CD'}]
const arr2 = [{id:3,name:'EF'}, {id:2,name:'CD'}]
const flatten = a => [].concat.apply([], a)
const noDuplicateProps = (a, b) => Object.keys(a).some(k => a[k] === b[k])
const combineAndDeDup = (...arrs) => {
return flatten(arrs).reduce((acc, item) => {
const uniqueItem = acc.findIndex(i => noDuplicateProps(i, item)) === -1
if (uniqueItem) return acc.concat([ item ])
return acc
}, [])
}
const deDuped = combineAndDeDup(arr1, arr2)
const megaDeDuped = combineAndDeDup(arr1, arr2, arr1, arr1, arr2, arr1)
console.log(deDuped)
console.log(megaDeDuped)
If you like clean ES6 try this:
Happy code :)
function arrayWithNoDuplicates(array, field) {
const arrayWithoutNoDuplicates = array.filter((value, index, self) =>
index === self.findIndex((t) => (
t[field] === value[field]
))
)
return arrayWithoutNoDuplicates
}
const arr1 = [{id:1,name:'AB'}, {id:2,name:'CD'}]
const arr2 = [{id:3,name:'EF'}, {id:2,name:'CD'}]
// The first param is the two merged arrays and the second the field you
// to filter by
console.log(arrayWithNoDuplicates([...arr1, ...arr2], 'id'))
By using lodash _.uniqWith(array, [comparator])
var objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }, { 'x': 1, 'y': 2 }];
_.uniqWith(objects, _.isEqual);
// => [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }]
var arr1 = [{ id: 1, name: 'AB' }, { id: 2, name: 'CD' }];
var arr2 = [{ id: 3, name: 'EF' }, { id: 3, name: 'XX' }];
arr1.forEach(element => {
arr2.forEach((el, idx) => {
if (element.id === el.id || element.name === el.name) {
delete arr2[idx]
}
});
});
let data = arr1.concat(arr2)
// or arr1 = arr1.concat(arr2)
// then your arr1 contains your unique array
data variable contains your unique array
Here is the one liner that compares by id.
let result = arr1.concat( arr2.filter( i2 => !arr1.find( i1 => i1.id == i2.id ) ) );
I have modified elements to show what happens for different objects with the same id. Swap arr1 with arr2 for which array you want to keep your preferred components. There seems to be no simple way to compare objects in JavaScript, you may use JSON.stringify but that depends on elements order. You can try it out at https://playcode.io/new/ :
var arr1=[{id:1,name:'AB'},{id:2,name:'CD'}];
var arr2=[{id:3,name:'EF'},{id:2,name:'GH'}];
let result;
result = arr1.concat( arr2.filter( i2 => !arr1.find( i1 => i1.id == i2.id ) ) );
console.log('RESULT: ' + JSON.stringify(result));
result = arr1.concat(
arr2.filter(
i2 => !arr1.find(
i1 => {
console.log('I1: ' + JSON.stringify(i1) + ' I2: ' + JSON.stringify(i2));
return i1.id == i2.id;}
)
)
);
console.log('RESULT: ' + JSON.stringify(result));
result = arr2.concat(
arr1.filter(
i1 => !arr2.find(
i2 => {
console.log('I1: ' + JSON.stringify(i1) + ' I2: ' + JSON.stringify(i2));
return i1.id == i2.id;}
)
)
);
console.log('RESULT: ' + JSON.stringify(result));
Both lodash function unionBy and unionWith can solve your problem.
If your objects has unique key, unionBy is the most elegant way to handle it.
var arr1 = [{id:1,name:'AB'},{id:2,name:'CD'}];
var arr2 = [{id:3,name:'EF'},{id:2,name:'CD'}];
var mergedWithoutDups = _.unionBy(arr1, arr2. 'id')
If your object has no unique key, use unionWith and isEqual instead. This will take deep comparison on all objects to remove duplicate.
var arr1 = [{id:1,name:'AB'},{id:2,name:'CD'}];
var arr2 = [{id:3,name:'EF'},{id:2,name:'CD'}];
var mergedWithoutDups = _.unionWith(arr1, arr2. _.isEqual)
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));