Remove duplicates conditionally in an array in JavaScript [duplicate] - javascript

This question already has answers here:
How to remove repeated entries from an array while preserving non-consecutive duplicates?
(5 answers)
Closed 6 years ago.
I am trying to remove duplicates in an array in JavaScript. The given array being
array = [1,1,1,1,1,1,1,1,1,,1,2,2,2,2,2,2,2,2,3,3,3,3,3,3,3,1,1,1,1,1,2,2,2,2,2,2,2,2]
resultant_array = [1,2,3,1,2]
Here the second 1 is not considered as a duplicate
OR
array = [1,1,1,1,1,1,1,1,1,1,1,1]
resultant_array = [1]
any ideas how i can do this

You can use reduce like this:
var array = [1,1,1,1,1,1,1,1,1,,1,2,2,2,2,2,2,2,2,3,3,3,3,3,3,3,1,1,1,1,1,2,2,2,2,2,2,22];
var result = array.reduce(function(r, e) {
if(r[r.length - 1] != e) // if the last element in the result is not equal to this item, then push it (note: if r is empty then r[-1] will be undefined so the item will be pushed as any number is != undefined)
r.push(e);
return r;
}, []);
console.log(result);

var arr = [1,1,2,2,3,3];
var obj = {};
for(var i in arr) {
obj[arr[i]] = true;
}
var result = [];
for(var i in obj) {
result.push(i);
}
I set the keys of the object as the value of the array and there can't be multiple keys with the same value. Then I took all the keys and put it in the result.

You could check the predecessor with Array#reduce
var array = [1, 1, 1, 1, 1, 1, 1, 1, 1, , 1, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2],
result = array.reduce(function (r, a) {
return r[r.length - 1] === a ? r : r.concat(a);
}, []);
console.log(result);
Or use Array#filter and an object for the last value.
var array = [1, 1, 1, 1, 1, 1, 1, 1, 1, , 1, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2],
result = array.filter(function (a, i, aa) {
return this.last !== a && (this.last = a, true);
}, { last: undefined });
console.log(result);

Related

How to replace duplicate objects from array

I know there are multiple ways to remove duplicates from arrays in javascript, the one i use is
let originalArray = [1, 2, 3, 4, 1, 2, 3, 4]
let uniqueArray = array => [...new Set(array)]
console.log(uniqueArray) -> [1, 2, 3, 4]
what i want is something similar but instead of removing the duplicates, to replace it with whatever string or number i want, like this
console.log(uniqueArray) -> [1, 2, 3, 4, "-", "-", "-", "-"]
this has to work with any order, like
[1, 2, 3, 3, 4, 5, 7, 1, 6]
result -> [1, 2, 3, "-", 4, 5, 7, "-", 6]
i tested this solution
const arr = [1, 2, 3, 1, 2, 3, 2, 2, 3, 4, 5, 5, 12, 1, 23, 4, 1];
const deleteAndInsert = uniqueList => {
const creds = uniqueList.reduce((acc, val, ind, array) => {
let { count, res } = acc;
if (array.lastIndexOf(val) === ind) {
res.push(val);
} else {
count++;
};
return { res, count };
}, { count: 0, res: [] });
const { res, count } = creds;
return res.concat(" ".repeat(count).split(" "));
};
console.log(deleteAndInsert(arr));
but only adds it at the end of the uniques, and also, only works with numbers
i want it to work with strings too, like dates as an example
["2021-02-22", "2021-02-23", "2021-02-22", "2021-02-28"]
You could still use a Set and check if the value is in the set.
const
unique = array => array.map((s => v => !s.has(v) && s.add(v) ? v : '-')(new Set));
console.log(...unique([1, 2, 3, 4, 1, 2, 3, 4]));
console.log(...unique([1, 2, 3, 3, 4, 5, 7, 1, 6]));
Just create new Array, use 1 set to control which element appeared, if one element appears more than 1, push new one character like '-'
let originalArray = [1, 2, 3, 4, 1, 2, 3, 4];
let newArray = [];
let set = new Set();
for (let i = 0; i < originalArray.length; i++) {
if(!set.has(originalArray[i])) {
newArray.push(originalArray[i]);
set.add(originalArray[i]);
} else {
newArray.push('-');
}
}
console.log(newArray);
You could do it with reduce
const dashDupes = array => array.reduce((acc, e) => {
if(acc.idx[e])
acc.arr.push('-')
else{
acc.arr.push(e);
}
acc.idx[e] = true;
return acc;
},{idx:{},arr:[]}).arr
console.log(...dashDupes([1, 2, 3, 4, 1, 2, 3, 4]))
console.log(...dashDupes([1, 2, 3, 3, 4, 5, 7, 1, 6]))
This is a very simple approach to the problem:
function uniqueReplace(arr, rep) {
let res = [];
for (x of arr) {
res.push(res.includes(x) ? rep : x);
}
return res;
}
console.log(...uniqueReplace([1, 2, 3, 4, 1, 2, 3, 4], '-'));
console.log(...uniqueReplace([1, 2, 3, 3, 4, 5, 7, 1, 6], '-'));

Why can't I use an array as the 'specified condition' in a while loop?

So I have this code:
var myArray = [];
var value = 5;
while (myArray != [5, 4, 3, 2, 1, 0]) {
myArray.push(value)
value--;
console.log(myArray);
}
when I look at the console, it goes on for an infinite loop like so..
[ 5 ]
[ 5, 4 ]
[ 5, 4, 3 ]
[ 5, 4, 3, 2 ]
[ 5, 4, 3, 2, 1 ]
[ 5, 4, 3, 2, 1, 0 ]
[ 5, 4, 3, 2, 1, 0, -1 ]
[ 5, 4, 3, 2, 1, 0, -1, -2 ]
[ 5, 4, 3, 2, 1, 0, -1, -2, -3 ]
..........
Why doesn't it stop at [5,4,3,2,1,0] ? myArray = that at a point and the for loop should stop no?
Sorry for the noob question.
JavaScript does not provide built-in support for structural-equality of Arrays, but it's straightforward to implement a comparator:
function arraysEqual(a, b, orderSensitive = true) {
// Function from https://stackoverflow.com/a/16436975/159145
// But modified to add the `orderSensitive` option.
if (a === b) return true;
if (a == null || b == null) return false;
if (a.length != b.length) return false;
if (!orderSensitive) {
a = Array.from(a).sort();
b = Array.from(b).sort();
}
for (var i = 0; i < a.length; ++i) {
if (a[i] !== b[i]) return false;
}
return true;
}
function yourCode() {
var myArray = [];
var value = 5;
const finalArray = [5, 4, 3, 2, 1, 0];
while (!arraysEqual(myArray,finalArray)) {
myArray.push(value)
value--;
console.log(myArray);
}
}
you can use the following way to fix the issue if index and values of both arrays are different
while(sortArray(myArray).toString() !== sortArray([5, 4, 3, 2, 1, 0]).toString()) {
// your code
}
sortArray(array) {
return array.filter((a, b) => a-b)
}
If you are sure the array index and values for both arrays are same you can use
while(myArray.toString() !== [5, 4, 3, 2, 1, 0].toString()) {
// your code
}
#Christopher Barreto and welcome to StackOverflow. Good luck with your interesting question.
although #Dai right with his full answer there is much simpler built in a way to convert array to string and then compare them.
That will work for you:
var myArray = [];
var value = 5;
while (myArray.toString() != [5, 4, 3, 2, 1, 0].toString()) {
myArray.push(value)
value--;
console.log(myArray);
}
Or this if you prefer:
while ((''+myArray) != ('' + [5, 4, 3, 2, 1, 0]))

How to remove one subset from an array in JS?

Let's say I have an array such as: [1, 1, 2, 2, 3, 3, 4, 5]
And I want to remove this array of elements [1, 2, 3, 4, 5]
So in the end I want to be left with [1, 2, 3]
I have tried using the method below but it removes all copies of the elements from the main array.
myArray = myArray.filter( function( el ) {
return !toRemove.includes( el );
} );
Here is a way to do it using filter, indexOf and splice.
const input = [1, 1, 2, 2, 3, 3, 4, 5];
function removeSubset(arr, subset) {
const exclude = [...subset];
return arr.filter(x => {
const idx = exclude.indexOf(x);
if (idx >= 0) {
exclude.splice(idx, 1);
return false;
}
return true;
});
}
console.log(removeSubset(input, [1, 2, 3, 4, 5]));
You could get a Map and count the values and filter by checking the count and decrement the count if found.
var array = [1, 1, 2, 2, 3, 3, 4, 5],
remove = [1, 2, 3, 4, 5],
map = remove.reduce((m, v) => m.set(v, (m.get(v) || 0) + 1), new Map),
result = array.filter(v => !map.get(v) || !map.set(v, map.get(v) - 1));
console.log(result);
One solution is looping on the array of elements to remove and for each one remove the first element found on the input array:
const input = [1, 1, 2, 2, 3, 3, 4, 5];
const removeItems = (input, items) =>
{
// Make a copy, to not mutate the input.
let clonedInput = input.slice();
// Search and remove items.
items.forEach(x =>
{
let i = clonedInput.findIndex(y => y === x);
if (i >= 0) clonedInput.splice(i, 1);
});
return clonedInput;
}
console.log(removeItems(input, [1,2,3,4,5]));
console.log(removeItems(input, [1,2]));
console.log(removeItems(input, [1,99,44,5]));
If you still want to use filter, you can use the items to remove as the this argument of the filter, something like this:
const input = [1, 1, 2, 2, 3, 3, 4, 5];
const removeItems = (input, items) =>
{
return input.filter(function(x)
{
let i = this.findIndex(y => y === x);
return i >= 0 ? (this.splice(i, 1), false) : true;
}, items.slice());
}
console.log(removeItems(input, [1,2,3,4,5]));
console.log(removeItems(input, [1,2]));
console.log(removeItems(input, [1,99,44,5]));
You can use Filter and Shitf and Sort
let arr = [1, 1, 2, 2, 3, 3, 4, 5]
let remove = [1, 3, 2, 4, 5].sort((a,b)=>a-b)
let op = arr.sort((a,b)=>a-b).filter(e => ( remove.includes(e) ? (remove.shift(), false) : true ))
console.log(op)

How can I get index of the value inside forEach loop?

Absolutely NewBee
How Can I find out the index of the value and not the value itself inside forEach loop Currently I have following code which just gives my the value of userAnswers :
correctAnswers: [], // [1, 2, 3, 1, 2, 1, 3, 3, 4, 3]
userAnswers: [], // [1, 2, 1, 1, 2, 1, 3, 3, 4, 3]
let tempArr = [];
const findingTotal = userAnswers.forEach(
(value, index) =>
value === correctAnswers[index]
? (Total += 1)
: tempArr.push(value)
);
In the above example I want to get index which is 2 and not the value (1) itself ?
correctAnswers: [], // [1, 2, 3, 1, 2, 1, 3, 3, 4, 3]
userAnswers: [], // [1, 2, 1, 1, 2, 1, 3, 3, 4, 3]
let tempArr = [];
let Total = 0;
userAnswers.forEach(
(value, index) =>
value === correctAnswers[index]
? (Total += 1)
: tempArr.push(index)
);
tempArr.push(index), findingTotal is not used too

Removing duplicates in an ordered array

What I'm trying to do is find how many times an array elements repeats itself in array, push the element along with the number of repeats it has in an object and after that delete the element and all its duplicates.
At the moment I have this function :
function getDuplicates(arr) {
let lastIndex = null;
let obj = {};
for ( let i = 0; i < arr.length; i++ ) {
lastIndex = arr.lastIndexOf(arr[i]);
obj[arr[i]] = lastIndex + 1;
arr.splice(0, lastIndex + 1 );
}
console.log(obj);
}
getDuplicates([ 1, 1, 1, 1, 2, 2, 3, 3, 3, 3, 4, 4, 5, 5, 5, 6 ]);
which logs : { '1': 4, '2': 2, '3': 4, '5': 5 }
It works great for the first 3 numbers ( 1,2 and 3 ) but 4 doesnt show up, 5 is messed up and 6 doesnt show due to lastIndex +1. Am I missing something or is there a better way to do this ?
Thank you.
You can simplify a lot the logic. Just an object to count and an if statement to increment values or define as 1 if it wasn't defined.
function countDuplicates(arr) {
// Contains a pair of values an instances.
var counting = {};
// Iterate array: check if already counted. If yes, increment, if not define as 1.
for (el of arr) (counting[el]) ? counting[el]++ : counting[el] = 1;
console.log(counting);
return counting;
}
countDuplicates([ 1, 1, 1, 1, 2, 2, 3, 3, 3, 3, 4, 4, 5, 5, 5, 6 ]);
Adding, if you also want to get the unique elements, you can just use E6 set:
var set = new Set([ 1, 1, 1, 1, 2, 2, 3, 3, 3, 3, 4, 4, 5, 5, 5, 6 ]);
You can count and print as you would want like this:
function getDuplicates(arr) {
var counts = {};
arr.forEach(function(x) { counts[x] = (counts[x] || 0)+1; });
console.log(counts);
}
function getDuplicates(arr) {
let lastNum = null;
let obj = {};
for ( let i = 0; i < arr.length; i++ ) {
if (arr[i] != lastNum){
lastNum = arr[i];
obj[arr[i]] = 1;
}else{
obj[arr[i]]++;
}
}
console.log(obj);
}
You can simply use Array#reduce() to count the occurrences and Array#filter() to remove the duplicates
getDuplicates([1, 1, 1, 1, 2, 2, 3, 3, 3, 3, 4, 4, 5, 5, 5, 6]);
function getDuplicates(arr) {
var obj = arr.reduce((map, item) => (map[item] = ++map[item] || 1, map),{} );
var withoutDup = arr.filter((item, pos) => arr.indexOf(item) == pos);
console.log(JSON.stringify(obj));
console.log(JSON.stringify(withoutDup));
}
Here's one method how to solve it.
Firstly I've removed all duplicated elements from the given array, using new Set() and then iterated over it using Array#forEach and checked with Array#filter how many times given element appears in the passed array.
function getDuplicates(arr){
var filtered = [...new Set(arr)],
result = {};
filtered.forEach(function(v){
result[v] = arr.filter(c => c == v).length;
})
console.log(result);
}
getDuplicates([ 1, 1, 1, 1, 2, 2, 3, 3, 3, 3, 4, 4, 5, 5, 5, 6 ]);
Array#reduce solution.
function getDuplicates(arr) {
var res = arr.reduce(function(s, a) {
s[a] = arr.filter(c => c == a).length;
return s;
}, {});
console.log(res);
}
getDuplicates([1, 1, 1, 1, 2, 2, 3, 3, 3, 3, 4, 4, 5, 5, 5, 6]);
It looks as if you want to COUNT duplicates, but if all you want to do is remove duplicates (As headline states), as per #ChantryCargill s suggestion:
function removeDuplicates (arr) {
var results = [];
for(var i = 0; i < arr.length; i++) {
var item = arr[i];
if(results.indexOf(item) === -1) {
results.push(item);
}
}
return results;
}
console.log(removeDuplicates([ 1, 1, 1, 1, 2, 2, 3, 3, 3, 3, 4, 4, 5, 5, 5, 6 ]));
//[1, 2, 3, 4, 5, 6]
If you want to COUNT duplicates:
function getDuplicates(arr) {
var results = {};
for(var item of arr) {
if(!results[item]) {
results[item] = 0;
}
results[item]++;
}
return results;
}
console.log(getDuplicates([ 1, 1, 1, 1, 2, 2, 3, 3, 3, 3, 4, 4, 5, 5, 5, 6 ]));
//{"1":4,"2":2,"3":4,"4":2,"5":3,"6":1}
Try this:
function getDuplicates(){
var numbers=Array.prototype.slice.call(arguments);
var duplicates={};
for(var index in numbers){
if(numbers.indexOf(numbers[index])==index)
continue;
duplicates[numbers[index]]= (duplicates[numbers[index]] || 0) + 1;
}
return duplicates;
}
console.log(getDuplicates(1,2,3,1,1,3,4,5,6,7,8,6));
/*
prints {
1: 2,
3: 1,
6: 1
}
*/

Categories

Resources