I have an array like following simpler example:
array = [1,2,2,3,4,4,4,5,6,7,7,7,8,9]
and I would like to check and separate them into the following arrays:
uniqArray = [1,3,5,6,8,9]
dupArray = [[2,2],[4,4,4],[7,7,7]]
I have tried this
let array = [1,2,2,3,4,4,4,5,6,7,7,7,8,9]
let uniqArray = []
let dupArray = []
let tempArray = []
array.forEach((item, index) => {
if (item !== array[index 1]) {
uniqArray.push(item)
if (tempArray.length > 0) {
dupArray.push(tempArray)
tempArray = []
}
} else {
tempArray.push(item)
}
}
)
console.log(uniqArray) // [ 1, 2, 3, 4, 5, 6, 7, 8, 9]
console.log(dupArray) // [ [ 2 ], [ 4, 4 ], [ 7, 7 ] ]
but as you can see the first instance of the duplicate stays in the uniqArray.
also tried this which actually worked but I am not sure if it is the best solution:
let array = [1,2,2,3,4,4,4,5,6,7,7,7,8,9]
let arrayOfArrays = array.reduce((acc, curr) => {
if (acc[acc.length - 1].length === 0 || acc[acc.length - 1][0] === curr) {
acc[acc.length - 1].push(curr)
} else {
acc.push([curr])
}
return acc
}
, [[]]) // [[ 1 ],[ 2, 2 ],[ 3 ],[ 4, 4, 4 ],[ 5 ],[ 6 ],[ 7, 7, 7 ],[ 8 ],[ 9 ]]
let uniqItems = arrayOfArrays.filter(item => item.length === 1).map(item => item[0])
let duplicateItems = arrayOfArrays.filter(item => item.length > 1)
console.log("~ duplicateItems", duplicateItems) // [ [ 2, 2 ], [ 4, 4, 4 ], [ 7, 7, 7 ] ]
console.log("~ uniqItems", uniqItems) // [ 1, 3, 5, 6, 8, 9 ]
It would be awesome if anyone has a better solution to this!
CodePudding user response:
You can try using collections.Counter
:
def getUniqueAndDups(arr):
c = collections.Counter(arr)
unique = []
dups = []
for item in c:
if c[item] == 1:
unique.append(item)
else:
dups.append([item]*c[item])
return unique, dups
>>> uniqueArray, dupArray = getUniqueAndDups([1,2,2,3,4,4,4,5,6,7,7,7,8,9])
>>> uniqueArray
[1, 3, 5, 6, 8, 9]
>>> dupArray
[[2, 2], [4, 4, 4], [7, 7, 7]]
>>>
CodePudding user response:
let array = [1,2,2,3,4,4,4,5,6,7,7,7,8,9];
//sort the array
array.sort();
let unique = [];
let dupes = [];
let duptemp = [];
//iterative approach using traditional for loop
for(let i = 0; i < array.length; i ){
//if the next element in array is equal to current, add current
//to dupes
if(i 1 < array.length && array[i 1] === array[i]){
duptemp.push(array[i]);
//if next element in array is not equal to current
//and duptemp is has values, push into dupes and clear temp
} else if(i 1 < array.length && array[i 1] !== array[i] && duptemp.length > 0) {
duptemp.push(array[i]);
dupes.push(duptemp);
duptemp = [];
//if at the end of the array and duptemp has values,
//add to dupes
} else if(i 1 >= array.length && duptemp.length > 0){
duptemp.push(array[i]);
dupes.push(duptemp);
//it's unique
} else {
unique.push(array[i]);
}
}
console.log(unique);
console.log(dupes);
CodePudding user response:
You can do it with Map
const array = [1, 2, 2, 3, 4, 4, 4, 5, 6, 7, 7, 7, 8, 9];
const countMap = new Map();
// Count the occurence of each item and save it at a map.
for (const number of array) {
const count = countMap.get(number);
if (count) countMap.set(number, count 1);
else countMap.set(number, 1);
}
const unique = [];
const double = [];
// For each item at map, fill the unique and double array
for (const keyValue of countMap.entries()) {
const count = keyValue[1];
const number = keyValue[0];
if (count == 1) {
unique.push(number);
} else {
double.push(Array(count).fill(number));
}
}
console.log(unique);
console.log(double);
I think this is the most performatic way to do it with a large array, and it don't need to be sorted