how to fetch distinct objects in array : Javascript - javascript

I am trying to fetch unique objects from an array which may have duplicate objects. I have tried new Set and new Map but i still haven't gotten my result.
For example i have the following array of objects
const myArray = [{ x: 10, y: 22}, { x: 11, y: 22}, { x: 12, y: 22}, { x: 12, y: 22}, { x: 12, y: 23}];
console.log([...new Set(myArray.map((item) => item.x && item.y ))]) // [22, 23]
when i want this
[{ x: 10, y: 22}, { x: 11, y: 22}, { x: 12, y: 22}, { x: 12, y: 23}];
it should remove the fourth object in myArray, since it is repeating

You can use reduce for that along with some:
const myArray = [{ x: 10, y: 22}, { x: 11, y: 22}, { x: 12, y: 22}, { x: 12, y: 22}, { x: 12, y: 23}];
const Filtered = [];
const filterDuplicates = myArray.reduce((arr, el) => {
if(!arr.some(current => current.x === el.x && current.y === el.y)) {
arr.push(el);
}
return arr;
}, Filtered);
console.log(Filtered);

What your map returns as follows
myArray.map((item) => item.x && item.y) // [ 22, 22, 22, 22, 23 ]
because it first check wheather the item.x is truthy or not. As it true always so it returns the value after &&
and when you apply the set, It will filter the unique value from the array
[...new Set(myArray.map((item) => item.x && item.y))] // [ 22, 23 ]
Alternate apprach
const myArray = [
{ x: 10, y: 22 },
{ x: 11, y: 22 },
{ x: 12, y: 22 },
{ x: 12, y: 22 },
{ x: 12, y: 23 },
];
const strArray = myArray.map(({ x, y }) => `${x}/${y}`);
const str = [...new Set(strArray)];
const result = str.map((str) => {
const [x, y] = str.split("/");
return { x, y };
});
console.log(result);

Related

get duplicates in array of objects

I have array of objects.
let coordinates = [
{ x: 8, y: 1 },
{ x: 8, y: 3 },
{ x: 6, y: 5 },
{ x: 4, y: 6 },
{ x: 3, y: 7 },
{ x: 6, y: 5 },
{ x: 3, y: 3 },
{ x: 1, y: 4 },
{ x: 3, y: 3 }
]
I stumbled upon this blog and this stackoverflow question but it only lets me find duplicates based on one property but I want to get the duplicate objects based on x and y properties like this:
[
{ x: 6, y: 5 },
{ x: 3, y: 3 }
]
We apply filter to check the uniquness of index, say if element is duplicate it will count the initial index and the current index will be filtered out.
var coordinates = [ { x: 8, y: 1 }, { x: 6, y: 5 }, { x: 4, y: 6 }, { x: 3, y: 7 }, { x: 6, y: 5 }, { x: 3, y: 3 }, { x: 1, y: 4 }, { x: 3, y: 3 }];
var result = coordinates.filter((val, i, self)=>self.findIndex(k=>k.x==val.x && k.y == val.y)!=i);
console.log(result)
UPDATE
coordinates = [ { x: 6, y: 5 }, { x: 6, y: 5 }, { x: 6, y: 5 },{ x: 4, y: 6 }, { x: 3, y: 7 }, { x: 6, y: 5 }, { x: 3, y: 3 }, { x: 3, y: 3 }, { x: 1, y: 4 }, { x: 3, y: 3 },{ x: 6, y: 5 }];
result = coordinates.reduce((acc, elem)=>{
key = Object.values(elem).join('|');
acc.unique[key] = acc.unique[key] || [];
acc.unique[key].length >0 ? acc.duplicate[key] = elem : acc.unique[key].push(elem);
return acc;
},{unique:{},duplicate:{}});
duplicate = Object.values(result.duplicate);
unique = Object.values(result.unique);
console.log(duplicate);
console.log(unique);
All the answers are not fully correct, because they don't apply to arrays with more than 2 duplicates of the same value, i.e.:
var coordinates = [
{ x: 8, y: 1 },
{ x: 8, y: 1 },
{ x: 8, y: 1 }
]
I used JSON.stringify() and Set structure to get unique duplicates from an array. And for the output I parsed strings back to the objects.
var coordinates = [
{ x: 8, y: 1 },
{ x: 6, y: 5 },
{ x: 4, y: 6 },
{ x: 3, y: 7 },
{ x: 6, y: 5 },
{ x: 3, y: 3 },
{ x: 1, y: 4 },
{ x: 3, y: 3 },
{ x: 3, y: 3 },
]
const duplicates = new Set();
const reducer = (set, val, index, arr) => arr.findIndex(k => k.x == val.x && k.y == val.y) != index ? set.add(JSON.stringify(val)) : set
coordinates.reduce(reducer, duplicates)
console.log(Array.from(duplicates).map(el => JSON.parse(el)))
You can use reduce and another array. Inside reduce callback use x & y to create an object key and check if that key exist in accumulator object. If it exist then push tyhe value to the dupArray
let coordinates = [
{ x: 8, y: 1 },
{ x: 8, y: 3 },
{ x: 6, y: 5 },
{ x: 4, y: 6 },
{ x: 3, y: 7 },
{ x: 6, y: 5 },
{ x: 3, y: 3 },
{ x: 1, y: 4 },
{ x: 3, y: 3 }
];
let dupArray = [];
let dups = coordinates.reduce((acc, curr) => {
const crtKey = '' + curr.x + '' + curr.y;
if (!acc[crtKey]) {
acc[crtKey] = 1;
} else {
dupArray.push(curr);
}
return acc;
}, {});
console.log(dupArray)
this filters only the duplicate array Objects by iterating all the Array items and for each item, iterating the Array again, using some to check if that specific item was anywhere in the array (arr) in a location before the current one (idx1) and also comparing the current item with the checked items in the some iterator by casting both to "string"
let coordinates = [
{ x: 8, y: 1 },
{ x: 8, y: 3 },
{ x: 6, y: 5 },
{ x: 4, y: 6 },
{ x: 3, y: 7 },
{ x: 6, y: 5 },
{ x: 3, y: 3 },
{ x: 1, y: 4 },
{ x: 3, y: 3 }
]
const dups = coordinates.filter(({x, y}, idx1, arr) =>
arr.some(({x:x2,y:y2}, idx2) => idx2 < idx1 && ""+x+y == ""+x2+y2 )
)
console.log( dups )
To make the check more robust, by allowing comparison of any key, what-so-ever JSON.stringify can be used to compare the arrays (assuming all array items are Objects:
const dups = coordinates.filter((item, idx1, arr) =>
arr.some((item2, idx2) => idx2 < idx1 && JSON.stringify(item) == JSON.stringify(item2))

How to update values not present in one array of objects from another array of objects?

I have two arrays of objects which contain a huge amount of data.
The structure of these two arrays goes something like this.
arr1 = [
{x: 1, y: '2018-01-01'},
{x: 2, y: '2018-01-02'},
{x: 3, y: '2018-01-03'},
{x: 5, y: '2018-01-05'},
....
]
arr2 = [
{x: 1, y: '2018-01-01'},
{x: 2, y: '2018-01-02'},
{x: 3, y: '2018-01-03'},
{x: 4, y: '2018-01-04'},
{x: 5, y: '2018-01-05'},
{x: 6, y: '2018-01-08'}
]
I want to update arr2 in such a way that it updates the array of objects with values that are only present in arr1 and drop any values not present in arr1. Note, I want to update the original arr2 and not return a new array.
I tried iterating through individual arrays and remove values not present but not luck.
You could get a map and iterate from the end for splicing unknown items or update changed values.
var arr1 = [{ x: 1, y: '2018-01-01x' }, { x: 2, y: '2018-01-02' }, { x: 3, y: '2018-01-03' }, { x: 5, y: '2018-01-05' }],
arr2 = [{ x: 1, y: '2018-01-01' }, { x: 2, y: '2018-01-02' }, { x: 3, y: '2018-01-03' }, { x: 4, y: '2018-01-04' }, { x: 5, y: '2018-01-05' }, { x: 6, y: '2018-01-08' }],
map = arr1.reduce((m, { x, y }) => m.set(x, y), new Map),
i = arr2.length;
while (i--) {
if (map.has(arr2[i].x)) {
if (map.get(arr2[i].x) !== arr2[i].y) {
arr2[i].y = map.get(arr2[i].x);
}
} else {
arr2.splice(i, 1);
}
}
console.log(arr2);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Get every fourth of array and check between

I have array like this:
let arr = [
{ x: 31, y: 8 }, // get 1
{ x: 32, y: 8, monster: { is: true, id: '19216' } }, // get special
{ x: 32, y: 9 },
{ x: 32, y: 10 },
{ x: 32, y: 11 }, // get 4
{ x: 32, y: 12 },
{ x: 32, y: 13 },
{ x: 32, y: 14 },
{ x: 32, y: 15 }, // get 8
{ x: 32, y: 16 } // get last
];
what I want to achieve is to get every fourth, get special one (the one with monster object) and also last one. So the output would be
[
{x: 31, y: 8},
{x: 32, y: 8, monster: { is: true, id: '19216' } },
{x: 32, y: 11},
{x: 32, y: 15},
{x: 32, y: 16}
]
It was easy to get every fourth and last one like this:
let arrThinned = [];
for (let i = 0; i < arr.length; i = i + 4) {
arrThinned.push({
x: arr[i].x,
y: arr[i].y,
});
}
if((arr.length - 1) % 4 !== 0) {
/* add also last one if not already added */
arrThinned.push({
x: arr[arr.length - 1].x,
y: arr[arr.length - 1].y
});
};
but I can't figure out how to additionally check if there is this special one beetwen every fourth and also add it to thinnedArr array. I need to keep the order. Demo of above code.
Here, use filter
let arr = [
{ x: 31, y: 8 }, // get 1
{ x: 32, y: 8, monster: { is: true, id: '19216' } }, // get special
{ x: 32, y: 9 },
{ x: 32, y: 10 },
{ x: 32, y: 11 }, // get 4
{ x: 32, y: 12 },
{ x: 32, y: 13 },
{ x: 32, y: 14 },
{ x: 32, y: 15 }, // get 8
{ x: 32, y: 16 } // get last
];
let newArr = arr.filter((e,i,ar) => (i%4 === 0 || e.monster || i===ar.length-1));
console.log(newArr);
Used .flatMap() to sort out all required objects. A custom function based on this answer counts how many keys each object had so that if an object had more than 2 keys it was considered special.The version in demo is streamlined into one line.
/** objSize(object)
Utility that returns a given Object's number of non-enumerated property keys it
has (String and Symbol).
*/
const objSize = obj => {
let strings = Object.getOwnPropertyNames(obj).length;
let symbols = Object.getOwnPropertySymbols(obj).length;
return strings + symbols;
}
Further details about .flatMap() are commented in demo.
let array = [
{ x: 31, y: 8 }, // get 1
{ x: 32, y: 8, z: { is: true, id: '19216' } },
{ x: 32, y: 9 },
{ x: 32, y: 10 },
{ x: 32, y: 11 }, // get 4
{ x: 32, y: 12 },
{ x: 32, y: 13 },
{ x: 32, y: 14 },
{ x: 32, y: 15 }, // get 8
{ x: 32, y: 16 } // get last
];
const objSize = obj => Object.getOwnPropertyNames(obj).length + Object.getOwnPropertySymbols(obj).length;
/*
.flatMap() is an array method that is basically a
combonation of `.map()` and `.flat()`. Here it is running
a function of 4 ternary controls:
1. if current index is 0:
(idx === 0)
return [xy]
2. if current index is a factor of 4:
(idx % 4 === 0)
return [xy]
3. if current xy has more than 2 keys:
(objSize(xy) > 2)
return [xy]
4. if current index is the last:
(idx === array.length - 1)
return [xy]
5. otherwise return []
each return is an array which is flattened when the final
array is returned. Therefore an empty array is a clean
removal which means no nulls, spaces, or empty values.
*/
let result = array.flatMap((xy, idx) => xy === 0 ? [xy] : idx % 4 === 0 ? [xy] : objSize(xy) > 2 ? [xy] : idx === array.length - 1 ? [xy] : []);
console.log(JSON.stringify(result));

Is it possible to search a object in an array with both of its properties

I have the following code
const xPosition = coordinates.find(position => position.x === avoidObstacleX);
This returns me the coordinates {x: 26, y: 10} this is not wrong, but I have another coordinate that is the one I will like to output which is {x: 26, y: 11} Is there a way I can pass two parameters to the find method?
You could use two variables (not parameters to the find method itself), like you already use one:
function findObstacle(coordinates, avoidObstacleX, avoidObstacleY) {
return coordinates.find(position => position.x === avoidObstacleX
&& position.y === avoidObstacleY);
}
const xyPosition = findObstacle(coordinates, avoidObstacleX, avoidObstacleY);
But from the other answer I now learn that there are two interpretations of your question...
find only retrieves a single element, you need to use the filter method:
const coordinates = [ {x: 26, y: 10}, {x: 26, y: 11}, {x: 12, y: 34} ]
const avoidObstacleX = 26;
// returns [ {x: 26, y: 10}, {x: 26, y: 11} ]
const xPosition = coordinates.filter(position => position.x === avoidObstacleX);
To pass one value:
const coordinates= [
{x: 26, y: 10},
{x: 26, y: 11},
{x: 36, y: 6},
{x: 7,y: 8}
]
const avoidObstacleX=26;
let result = coordinates.filter(position=> {
return position.x === avoidObstacleX ;
})
console.log(result)
You can pass two values:
const coordinates= [
{x: 26, y: 11},
{x: 26, y: 11},
{x: 26, y: 11},
{x: 7,y: 8}
]
function find(avoidObstaclex,avoidObstacley){
let result= coordinates.filter(position=> {
return position.x === avoidObstaclex && position.y === avoidObstacley ;
})
return result;}
const avoidObstacleX=26;
const avoidObstacleY=11;
console.log(find(avoidObstacleX,avoidObstacleY))

How to reverse all arrays inside an object

var data = {
id: 1,
track: {
"1": [
{x: 10, y: 10},
{x: 11, y: 11},
{x: 12, y: 12}
],
"2": [
{x: 10, y: 10},
{x: 11, y: 11},
{x: 12, y: 12}
]
}
}
console.log(data.track);
var rev = data.track["1"].reverse();
console.log(rev);
How can i reverse every array inside "track" object? But I showed you above, that i am able to reverse array, by selecting it by key, but can i literally reverse every array inside "track" object?
Use Object.keys() to find all keys in your data structure
var data = {
id: 1,
track: {
"1": [
{x: 10, y: 10},
{x: 11, y: 11},
{x: 12, y: 12}
],
"2": [
{x: 10, y: 10},
{x: 11, y: 11},
{x: 12, y: 12}
]
}
}
var keys = Object.keys(data.track);
var count = keys.length;
for (var i=0;i<count;i++)
{
var rev = data.track[keys[i]].reverse();
console.log(rev);
}
It's simple. Just loop the data.track to get reverse result.
for (var i in data.track) {
console.log(data.track[i].reverse());
}

Categories

Resources