I'm trying to compare 2 array of objects together and remove the duplicates. For example...
var array1 = [0, 1, 2, 3, 4, 5, 6];
var array2 = [7, 8, 1, 2, 9, 10];
How can I check the array2 for any element of array1 and if true then remove that from array2 to eliminate the duplication.
The expected result: array 2 = [7, 8, 9, 10]
Any help would be appreciated, thanks
If the array include primitive types you can use indexOf and array#reduce
const array1 = [0, 1, 2, 3, 4, 5, 6]
const array2 = [7, 8, 1, 2, 9, 10]
var result = array2.filter((num) => {
return array1.indexOf(num) === -1;
});
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
In case of an object, you can get the unique values in second array in comparison to first, please use array#reduce and array#some.
const person1 = [{"name":"a", "id":0},{"name":"A", "id":1},{"name":"B", "id":2},{"name":"C", "id":3},{"name":"D", "id":4},{"name":"E", "id":5},{"name":"F", "id":6}]
const person2 = [{"name":"G", "id":7},{"name":"H", "id":8},{"name":"A", "id":1},{"name":"B", "id":2},{"name":"I", "id":9}, {"name":"J", "id":10}]
var unique = person2.reduce((unique, o) => {
let isFound = person1.some((b) => {
return b.id === o.id;
});
if(!isFound)
unique.push(o);
return unique;
},[]);
console.log(unique);
.as-console-wrapper { max-height: 100% !important; top: 0; }
just filter second array.
const array1 = [0, 1, 2, 3, 4, 5, 6];
const array2 = [7, 8, 1, 2, 9, 10];
const newArray = array2.filter(i => !array1.includes(i));
console.log(newArray);
You can use do this:
var array1 = [0, 1, 2, 3, 4, 5, 6];
var array2 = [7, 8, 1, 2, 9, 10];
/* run a filter function for every value in array2 and returned the final filtered array */
var array3 = array2.filter(function(currentValue, index, arr){
return (array1.indexOf(currentValue) === -1); /* this will check whether currentValue exists in aray1 or not. */
});
console.log(array3) /* filtered array */
This should deliver what you want. Or another way:
var array1 = [0, 1, 2, 3, 4, 5, 6];
var array2 = [7, 8, 1, 2, 9, 10];
var duplicateRemoved = [];
/* run a function for every value in array2 and collect the unique value in a new array */
array2.forEach(function(currentValue, index, arr){
if (array1.indexOf(currentValue) === -1) {
duplicateRemoved.push(currentValue);
}
});
console.log(duplicateRemoved)
This should work in your situation unless there are some other external factors associated with it.
Related
I need to check whether one array contains all of the elements of another array, including the same duplicates. The second array can have extra elements. I'm using every...includes, but it's not catching that the second array doesn't have the right duplicates.
For example:
const arr1 = [1, 2, 2, 3, 5, 5, 6, 6]
const arr2 = [1, 2, 3, 5, 6, 7]
if(arr1.every(elem => arr2.includes(elem))){
return true // should return false because arr2 does not have the same duplicates
}
Thanks!
Edit: arr1 is one of many arrays that I am looping through which are coming out of a graph traversal algorithm, so I'd like to avoid restructuring them into an object to create a dictionary data structure if possible.
Try creating this function:
function containsAll (target, toTest) {
const dictionary = {}
target.forEach(element => {
if (dictionary[element] === undefined) {
dictionary[element] = 1;
return;
}
dictionary[element]++;
});
toTest.forEach(element => {
if (dictionary[element] !== undefined)
dictionary[element]--;
})
for (let key in dictionary) {
if (dictionary[key] > 0) return false;
}
return true;
}
Then invoke it like this:
const arr1 = [1, 2, 2, 3, 5, 5, 6, 6]
const arr2 = [1, 2, 3, 5, 6, 7]
console.log(containsAll(arr1, arr2)) // returns false
const arr1 = [1, 2, 2, 3, 5, 5, 6, 6];
//const arr2 = [1, 2, 3, 5, 6, 7];
const arr2 = [1, 2, 2, 3, 5, 5];
let includesAll1 = true;
let includesAll2 = true;
const checkObj1 = {
};
const checkObj2 = {
};
arr1.forEach((el)=> {
if(checkObj1[el] === undefined) {
checkObj1[el] = 1;
} else {
checkObj1[el]++;
}
});
arr2.forEach((el)=> {
if(checkObj2[el] === undefined) {
checkObj2[el] = 1;
} else {
checkObj2[el]++;
}
});
const check1Keys = Object.keys(checkObj1);
const check2Keys = Object.keys(checkObj2);
if(check1Keys.length > check2Keys.length) {
includesAll2 = false;
check2Keys.forEach((key)=> {
const value1 = checkObj1[key];
const value2 = checkObj2[key];
if(!arr1.includes(parseInt(key)) || value1 != value2) {
includesAll1 = false;
}
});
} else {
includesAll1 = false;
check1Keys.forEach((key)=> {
const value1 = checkObj1[key];
const value2 = checkObj2[key];
console.log(value1, value2, key);
if(!arr2.includes(parseInt(key)) || value1 != value2) {
includesAll2 = false;
}
});
}
console.log(includesAll1);
console.log(includesAll2);
Does this solve your problem?
const arr = [1, 2, 3, 5, 6, 7, 2, 10, 2, 3, 2];
const subArr = [1, 2, 2, 3, 2]
const contains = subArr.every(num => subArr.filter(n => n == num).length <= arr.filter(n => n== num).length);
console.log(contains);
You indicate order does not matter in your comments. That makes this very simple.
Sort both arrays
Check if corresponding elements are equal
consider errors associated with sparse or short arrays
Use .reduce() to boil it down to a single result
So this really comes down to a single statement once the arrays are sorted:
matcher.reduce((acc, value , idx)=>matcher[idx] === test[idx], false);
You also mentioned testing this against many arrays. So the full example below does that for demo purposes.
let toMatch = [1, 2, 2, 3, 5, 5, 6, 6]
let arrayOfArrays = [[1,2],[1, 2, 3, 5, 6, 7, 3, 9, 8, 2, 7],[1, 2, 3, 3, 6, 7],[1, 3, 3, 5, 6, 7],[1, 2, 3, 5, 6, 6], [3,5,2,1,6,2,5,6]];
let toMatchSorted = toMatch.slice().sort();
arrayOfArrays.forEach(arr=>{
let toTestSorted = arr.slice().sort();
let out = toMatchSorted.reduce((acc, value , idx)=>toMatchSorted[idx] === toTestSorted[idx], false);
console.log(`Input: ${arr}, Result: ${out}`);
});
Trying to sort an array and sort() is switching just 1 value and adding the largest to the middle of the array. Could anyone help me understand what is happening?
My Results that I get are:
Original Array: [2643832795, 1, "3", 10, 3, 5]
New Array: [1, 10, 2643832795, 3, 3, 5]
let startArray = [2643832795, 1, "3", 10, 3, 5];
function bigSorting(unsorted) {
let newArray = [];
unsorted.forEach(el => {
if(typeof(el) == "string")
{ newArray.push(parseInt(el)) }
else { newArray.push(parseInt(el)) }
});
newArray.sort();
console.log(startArray);
console.log(newArray);
}
bigSorting(startArray);
It's using lexical comparison of strings. You can use a comparison function that coerces to numbers and subtracts for comparison
let startArray = [2643832795, 1, "3", 10, 3, 5];
function bigSorting(unsorted) {
let newArray = [];
unsorted.forEach(el => {
if(typeof(el) == "string")
{ newArray.push(parseInt(el)) }
else { newArray.push(parseInt(el)) }
});
newArray.sort();
console.log(newArray);
console.log(startArray);
console.log(unsorted.sort((x,y)=>x-y))
}
bigSorting(startArray);
you're very close :-)
let startArray = [2643832795, 1, "3", 10, 3, 5];
function bigSorting(unsorted) {
const newArray = unsorted.map(x => parseInt(x, 10));
newArray.sort((a, b) => a > b ? 1 : -1);
return newArray;
}
console.log(startArray);
console.log(bigSorting(startArray));
You're getting a lexicographical sort (e.g. convert objects to strings, and sort them in dictionary order), which is the default sort behavior in Javascript: Refer Docs
In ES6, you can simplify this with arrow functions:
unsorted.sort((a, b) => a - b);
So this should be like:
let startArray = [2643832795, 1, "3", 10, 3, 5];
function bigSorting(unsorted) {
let newArray = [];
unsorted.forEach(el => {
if(typeof(el) == "string")
{ newArray.push(parseInt(el)) }
else { newArray.push(parseInt(el)) }
});
newArray.sort((a, b) => a - b);
console.log(startArray);
console.log(newArray);
}
It’s sorting as it should. It sorts accordingly as it would sort a list of strings.
var list = [2643832795, 1, "3", 10, 3, 5];
When you write list.sort() it just sorts as would sort any list of strings according to each character's Unicode code point value.
So, 1 comes first then 2, 3 and so on. So even if it's 2643832795, it would come before 3.
If you want to sort this treating them as integers, you should supply a callback something like this:
var list = [2643832795, 1, "3", 10, 3, 5];
var newList = list.map(i=>parseInt(i)); //Convert the strings in the list into integers
newList.sort((a, b) => a-b);
console.log(newList)
Try this, hope it can help you.
var numbers = [2, 5, 8, 7, 1, 6, 10, 3, 4, 9];
var asc = numbers.sort((a, b) => a - b);
console.log(asc); // Output: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]. Numeric sort
numbers = [2, 5, 8, 7, 1, 6, 10, 3, 4, 9];
var des = numbers.sort((a, b) => b - a);
console.log(des); // Output: [10, 9, 8, 7, 6, 5, 4, 3, 2, 1]. Numeric descending sort
I'm trying to test my JS ability and i have no idea how to do the following.
I have an array of data var array = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];.
I want to pair the items and return a new array of arrays eg var newArray = [[1,2], [3,4], [5,6]]; ect
How would I got about this
var arr = [ 4, 1, 2, 8, 9, 0 ]
var newArray = []
for (var i=0; i<arr.length; i+=2) {
newArray.push([arr[i], arr[i+1]])
}
console.log(newArray)
I made a scalable function that you can use to do this for you but you can also configure it so that it is flexible enough to handle any number of objects that you want by passing in n.
const numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
function partitionListByN(list, n = 2, reverse) {
if(reverse) {
return [list.splice(list.length - n).reverse()].concat(list.length > 0 partitionListByN(list, n, reverse) : list)
}
return [list.splice(0, n)].concat(list.length > 0 ? partitionListByN(list, n) : list)
}
console.log(partitionListByN(numbers, 3));
Whats happening is you pass in a list, we are returning a list [firstPartition, shortenedListFromRecursiveCall] so this will go [[1, 2, 3], [4, 5, 6], [7, 8, 9], [10]] since I passed n in as 3. As you can see it defaults to 2 in the params list.
It also supports a reverse setting: console.log(partionListByN(numbers, 3, true)) this would yield [ [ 10, 9, 8 ], [ 7, 6, 5 ], [ 4, 3, 2 ], [ 1 ] ]
You could take a variable for the wanted chunk size and an index and iterate as long as some elements are available.
var array = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
size = 2,
chunks = [],
i = 0;
while (i < array.length) chunks.push(array.slice(i, i += size));
console.log(chunks);
.as-console-wrapper { max-height: 100% !important; top: 0; }
This question already has answers here:
Get all unique values in a JavaScript array (remove duplicates)
(91 answers)
Closed 3 years ago.
I received this question for practice and the wording confused me, as I see 2 results that it might want.
And either way, I'd like to see both solutions.
For example, if I have an array:
let arr = [1, 2, 4, 2, 3, 3, 4, 5, 5, 5, 8, 8, 9, 10];
I'm taking this as wanting the final result as either:
let finalResult = [1, 2, 3, 4, 5, 8, 9, 10];
OR:
let finalResult = [1, 9, 10];
The difference between the two being, one just removes any duplicate numbers and leaves the rest and the second just wants any number that isn't a duplicate.
Either way, I'd like to write two functions that does one of each.
This, given by someone else gives my second solution.
let elems = {},
arr2 = arr.filter(function (e) {
if (elems[e] === undefined) {
elems[e] = true;
return true;
}
return false;
});
console.log(arr2);
I'm not sure about a function for the first one (remove all duplicates).
Using Set and Array.from()
let arr = [1, 2, 4, 2, 3, 3, 4, 5, 5, 5, 8, 8, 9, 10];
console.log(Array.from(new Set(arr)));
Alternate using regex
regex explanation here
let arr = [1, 2, 4, 2, 3, 3, 4, 5, 5, 5, 8, 8, 9, 10];
let res = arr
.join(',')
.replace(/(\b,\w+\b)(?=.*\1)/ig, '')
.split(',')
.map(Number);
console.log(res);
Alternate using objects
let arr = [1, 2, 4, 2, 3, 3, 4, 5, 5, 5, 8, 8, 9, 10];
let obj = arr.reduce((acc, val) => Object.assign(acc, {
[val]: val
}), {});
console.log(Object.values(obj));
Just use a simple array.filter one-liner:
let arr = [1, 2, 4, 2, 3, 3, 4, 5, 5, 5, 8, 8, 9, 10];
let finalResult = arr.filter((e, i, a) => a.indexOf(e) == i).sort(function(a, b){return a - b});
console.log(finalResult);
You could use another filter statement if you wanted the second result:
let arr = [1, 2, 4, 2, 3, 3, 4, 5, 5, 5, 8, 8, 9, 10];
let finalResult = arr.filter((e, i, a) => a.filter(f => f == e).length == 1).sort(function(a, b){return a - b});
console.log(finalResult);
For the first part you can use Set() and Spread Syntax to remove duplicates.
let arr = [1, 2, 4, 2, 3, 3, 4, 5, 5, 5, 8, 8, 9, 10];
let res = [...new Set(arr)]
console.log(res)
For the second part you can use reduce()
let arr = [1, 2, 4, 2, 3, 3, 4, 5, 5, 5, 8, 8, 9, 10];
//to get the object with count of each number in array.
let obj = arr.reduce((ac,a) => {
//check if number doesnot occur before then set its count to 1
if(!ac[a]) ac[a] = 1;
//if number is already in object increase its count
else ac[a]++;
return ac;
},{})
//Using reduce on all the keys of object means all numbers.
let res = Object.keys(obj).reduce((ac,a) => {
//check if count of current number 'a' is `1` in the above object then add it into array
if(obj[a] === 1) ac.push(+a)
return ac;
},[])
console.log(res)
You can use closure and Map
let arr = [1, 2, 4, 2, 3, 3, 4, 5, 5, 5, 8, 8, 9, 10];
const build = ar => {
const mapObj = ar.reduce((acc, e) => {
acc.has(e) ? acc.set(e, true) : acc.set(e, false)
return acc
}, new Map())
return function(hasDup = true) {
if(hasDup) return [...mapObj.keys()]
else return [...mapObj].filter(([key, val]) => !val).map(([k, v])=> k)
}
}
const getArr = build(arr)
console.log(getArr())
console.log(getArr(false))
You can create both arrays in One Go
let arr = [1, 2, 4, 2, 3, 3, 4, 5, 5, 5, 8, 8, 9, 10];
let unique = new Set();
let repeated = Array.from(arr.reduce((acc, curr) => {
acc.has(curr) ? unique.delete(curr) : acc.add(curr) && unique.add(curr);
return acc;
}, new Set()));
console.log(Array.from(unique))
console.log(repeated)
You can use Array.prototype.reduce() create a hash object where the keys are the numbers in the array and the values are going to be the the repeated occurrence of numbers in the arr array variable..
Then using Object.keys():
Remove all duplicates Object.keys(hash)
Remove all duplicates but filtering with Array.prototype.filter() to get the numbers with only one occurrence
Code:
const arr = [1, 2, 4, 2, 3, 3, 4, 5, 5, 5, 8, 8, 9, 10];
const hash = arr.reduce((a, c) => (a[c] = (a[c] || 0) + 1, a), {});
// [1, 2, 3, 4, 5, 8, 9, 10];
const finalResultOne = Object.keys(hash);
// [1, 9, 10];
const finalResultTwo = Object.keys(hash).filter(k => hash[k] === 1);
console.log('finalResultOne:', ...finalResultOne);
console.log('finalResultTwo:', ...finalResultTwo);
You could sort the array before and filter the array by checking only one side for duplicates or both sides.
var array = [1, 2, 4, 2, 3, 3, 4, 5, 5, 5, 8, 8, 9, 10],
result1,
result2;
array.sort((a, b) => a - b);
result1 = array.filter((v, i, a) => a[i - 1] !== v);
result2 = array.filter((v, i, a) => a[i - 1] !== v && a[i + 1] !== v);
console.log(...result1);
console.log(...result2)
As many other have said, the first one is just [...new Set(arr)]
For the second, just filter out those that occur more than once:
const arr = [1, 2, 4, 2, 3, 3, 4, 5, 5, 5, 8, 8, 9, 10];
const count = (arr, e) => arr.filter(n => n == e).length
const unique = arr => arr.filter(e => count(arr, e) < 2)
console.log(unique(arr));
var arr = [1, 2, 4, 2, 3, 3, 4, 5, 5, 5, 8, 8, 9, 10];
var map = {};
var finalResult = [];
for (var i = 0; i < arr.length; i++) {
if (!map.hasOwnProperty(arr[i])) {
map[arr[i]] = true;
finalResult.push(arr[i]);
}
}
//if you need it sorted otherwise it will be in order
finalResult.sort(function(a, b) {
return a - b
});
console.log(finalResult);
I have the following code:
function uniteUnique(arr) {
//Create a single Array of value
arr = arguments[0].concat(arguments[1], arguments[2]);
//Reduce the Array to unique values only
arr = arr.reduce((pre, curr) => {
//Some function to reduce values
});
return arr;
}
uniteUnique([1, 3, 2], [5, 2, 1, 4], [2, 1]);
The goal is to produce a single Array containing only unique values while maintaining the order.
Currently it returns:
[1, 3, 2, 5, 2, 1, 4, 2, 1]
I'm wanting to reduce this to:
[1, 3, 2, 5, 4]
You can use Set for that:
function uniteUnique(...args) {
return [...new Set([].concat(...args))];
}
var u = uniteUnique([1, 3, 2], [5, 2, 1, 4], [2, 1]);
console.log(u);
It maintains insertion order, and by nature only contains unique values.
In ES5 you could do it by maintaining the used values as properties of a temporary object, while building the result array:
function uniteUnique(/* args */) {
return [].concat.apply([], arguments).reduce(function (acc, v) {
if (!acc[0][v]) acc[0][v] = acc[1].push(v); // assigns new length, i.e. > 0
return acc;
}, [ Object.create(null), [] ])[1];
}
var u = uniteUnique([1, 3, 2], [5, 2, 1, 4], [2, 1]);
console.log(u);
You can use the Set object since it already keeps your values unique in one object:
const mySet = new Set([1, 3, 2, 5, 2, 1, 4, 2, 1]);
// returns: Set { 1, 3, 4, 5 };
const arrayUniques = [...mySet];
console.log(arrayUniques);
// returns: [1, 3, 4, 5];