Remove duplicates from Array with Objects - javascript

I have something like this:
items: { _id: number; place: SomeAddressClassDto }[] = [];
sessionItem: { _id: number; place: SomeAddressClassDto };
createAddressList() {
this.service.getWorkingPlaces().subscribe((items) => {
this.items = items;
this.sessionItem = {
place: JSON.parse(sessionStorage.getItem('currentPlace')),
_id: this.items.length,
};
this.items.push(this.sessionItem);
// _.uniqBy(this.items, 'place')
const idx = items.findIndex((item) => this.service.comparePlaces(item.place,
this.service.getCurrentWorkingPlace()));
if (idx !== -1) this.radiobox.option = `${idx}`;
});
}
I am trying to remove any duplicates from 'items' array using the method _uniqBy, but it isn't working. I think it's because for this items._id are always different but items.place could be equal and if are I would like to get rid of this.
Maybe better way is to check is the same items.place is already in that array, but no idea how to do this.
EDIT:
To be more specify, items looks like this:
0: place: {name, street, city, etc...}
_id: 0
So it is possible to have very similar object whitch is differnet only by one property in place{}

I would suggest using the _id to determine if the value is unique. If you use place the value may always be unique since they could be different instances of the same class.(I can't tell from your code if this is the case)
createAddressList() {
this.service.getWorkingPlaces().subscribe((items) => {
this.items = items;
this.sessionItem = {
place: JSON.parse(sessionStorage.getItem('currentPlace')),
_id: this.items.length,
};
this.items.push(this.sessionItem);
_.uniqBy(this.items, '_id');
const idx = items.findIndex((item) => this.service.comparePlaces(item.place, this.service.getCurrentWorkingPlace()));
if (idx !== -1) {
this.radiobox.option = `${idx}`;
}
});
}
Alternately, you could use a property from inside place to determine if they are unique like this:
_.uniqBy(this.items, (x) => x.place && x.place.someOtherPropertyInsideOfPlace);

You can use Array.Prototype.reduce() and Array.prototype.find() to create an array that has no duplicates based on the place property.
As an example:
const test = [
{ _id: 1, place: 'a' },
{ _id: 2, place: 'a' },
{ _id: 3, place: 'a' },
{ _id: 4, place: 'b' },
{ _id: 5, place: 'c' },
]
const noDups = test.reduce((accum, current)=> {
if(!accum.find(item => item.place === current.place))
accum.push(current)
return accum
}, [])
console.log(noDups)
reduce() will create a new array (in this case, the accum variable is being initialized as an empty array), but only add new items in the new array if the .place property is unique, if it doesn't already find an item with the same .place property

declaring a simple object array with id and place properties.
Removing duplicates by javascript filter function.
filter function will remove the objects from array whose place is paris.
var arr = [{
_id: 1,
place: 'paris'
},
{
_id: 2,
place: 'tokyo'
},
{
_id: 3,
place: 'ontario'
},
{
_id: 4,
place: 'paris'
},
{
_id: 5,
place: 'karachi'
},
{
_id: 6,
place: 'paris'
},
{
_id: 7,
place: 'new york'
}
];
var newArray = arr.filter((self, item, index) => index.findIndex(t => (t.place === self.place)) === item);
console.log(newArray);

Related

Iterate over an array of object and change object value

I'm trying to iterate over an array of objects that looks like this:
const arr = [{
id: 1,
name: "John",
storeName: "Amazon",
price: 100,
isRecieved: false,
deliveryDate: some date
}, ....]
I'm iterating over the array with product ID that I received from the user, finding the relevant item according to it's id and changing the key "isRecieved" from false to true.
This is my code:
const filterReceivedProduct = (list, id) => {
const changeReceivedState = list.filter((item) => {
return item.id === id ? **item[isRecieved]** = true : item;
})
return changeReceivedState
}
But when I'm trying to access the object using bracket notation it return the value (in this case 'false') and I can't change the value to true..
What I'm doing wrong?
You don't need to use .filter() here. The filter method is for removing elements from an array. What you want to do is map each element/object to a new object, which has all the properties from the old object, containing an updated isRecieved property. To create a new object with all the properties of the old object, you can spread the properties and values from the old object into a new one ({...item}). You can then update the isRecived based on your whether the item id matched the id passed into your function:
const arr = [{
id: 1,
name: "John",
storeName: "Amazon",
price: 100,
isRecieved: false,
deliveryDate: 'some date'
}, {
id: 2,
name: "Alex",
storeName: "Apple",
price: 200,
isRecieved: false,
deliveryDate: 'some date2'
}];
const filterReceivedProduct = (list, id) =>
list.map(item => ({
...item,
isRecieved: item.id === id // sets isRecieved to true or false based on the equalty comparison
}));
const res = filterReceivedProduct(arr, 1);
console.log(res);
By creating a new object within the .map() callback, you're never mutating the original objects in your arr, treating everything as immutable.
Here filter make no sense. Filter use to filter some array based on condition. If you just want to change some property of an object inside array then use map for this purpose.
See below example.
const arr = [{
id: 1,
name: "John",
storeName: "Amazon",
price: 100,
isRecieved: false,
deliveryDate: 'some date'
}, {
id: 2,
name: "Doe",
storeName: "Amazon",
price: 100,
isRecieved: false,
deliveryDate: 'some date'
}];
filterReceivedProduct = (list, id) => {
return list.map(item => {
if(item.id === id) {
item.isRecieved = true;
}
return item;
});
}
console.log(filterReceivedProduct(arr, 1))

How to dedupe an array of objects by a key value pair?

// This is a large array of objects, e.g.:
let totalArray = [
{"id":"rec01dTDP9T4ZtHL4","fields":
{"user_id":170180717,"user_name":"abcdefg","event_id":516575,
}]
let uniqueArray = [];
let dupeArray = [];
let itemIndex = 0
totalArray.forEach(x => {
if(!uniqueArray.some(y => JSON.stringify(y) === JSON.stringify(x))){
uniqueArray.push(x)
} else(dupeArray.push(x))
})
node.warn(totalArray);
node.warn(uniqueArray);
node.warn(dupeArray);
return msg;
I need my code to identify duplicates in the array by a key value of user_id within the objects in the array. Right now, my code works to identify identical objects in the array, but I need it to identify dupes based on a key value inside the objects instead. How do I do this? I am struggling to figure out how to path the for each loop to identify the dupe based on the key value instead of the entire object.
Right now, my code works to identify identical objects in the array, but I need it to identify dupes based on a key value inside the objects instead. How do I do this?
Don’t compare the JSON representation of the whole objects then, but only their user_id property specifically.
totalArray.forEach(x => {
if(!uniqueArray.some(y => y.fields.user_id === x.fields.user_id)){
uniqueArray.push(x)
} else(dupeArray.push(x))
})
You could take a Set and push to either uniques or duplicates.
var array = [
{ id: 1, data: 0 },
{ id: 2, data: 1 },
{ id: 2, data: 2 },
{ id: 3, data: 3 },
{ id: 3, data: 4 },
{ id: 3, data: 5 },
],
uniques = [],
duplicates = [];
array.forEach(
(s => o => s.has(o.id) ? duplicates.push(o) : (s.add(o.id), uniques.push(o)))
(new Set)
);
console.log(uniques);
console.log(duplicates);
.as-console-wrapper { max-height: 100% !important; top: 0; }
One way is to keep a list of ids you found so far and act accordingly:
totalArray = [
{ id: 1, val: 10 },
{ id: 2, val: 20 },
{ id: 3, val: 30 },
{ id: 2, val: 15 },
{ id: 1, val: 50 }
]
const uniqueArray = []
const dupeArray = []
const ids = {}
totalArray.forEach( x => {
if (ids[x.id]) {
dupeArray.push(x)
} else {
uniqueArray.push(x)
ids[x.id] = true
}
})
for (const obj of uniqueArray) console.log("unique:",JSON.stringify(obj))
for (const obj of dupeArray) console.log("dupes: ",JSON.stringify(obj))

How to access an array of objects which is a key-value pair

i want to access the id 'qwsa221' without using array index but am only able to reach and output all of the array elements not a specific element.
i have tried using filter but couldnt figure out how to use it properly.
let lists = {
def453ed: [
{
id: "qwsa221",
name: "Mind"
},
{
id: "jwkh245",
name: "Space"
}
]
};
Use Object.keys() to get all the keys of the object and check the values in the array elements using . notation
let lists = {
def453ed: [{
id: "qwsa221",
name: "Mind"
},
{
id: "jwkh245",
name: "Space"
}
]
};
Object.keys(lists).forEach(function(e) {
lists[e].forEach(function(x) {
if (x.id == 'qwsa221')
console.log(x)
})
})
You can use Object.Keys method to iterate through all of the keys present.
You can also use filter, if there are multiple existence of id qwsa221
let lists = {
def453ed: [
{
id: "qwsa221",
name: "Mind"
},
{
id: "jwkh245",
name: "Space"
}
]
};
let l = Object.keys(lists)
.map(d => lists[d]
.find(el => el.id === "qwsa221"))
console.log(l)
you can do it like this, using find
let lists = {
def453ed: [
{
id: "qwsa221",
name: "Mind"
},
{
id: "jwkh245",
name: "Space"
}
]
};
console.log(
lists.def453ed // first get the array
.find( // find return the first entry where the callback returns true
el => el.id === "qwsa221"
)
)
here's a corrected version of your filter :
let lists = {def453ed: [{id: "qwsa221",name: "Mind"},{id: "jwkh245",name: "Space"}]};
// what you've done
const badResult = lists.def453ed.filter(id => id === "qwsa221");
/*
here id is the whole object
{
id: "qwsa221",
name: "Mind"
}
*/
console.log(badResult)
// the correct way
const goodResult = lists.def453ed.filter(el => el.id === "qwsa221");
console.log(goodResult)
// filter returns an array so you need to actually get the first entry
console.log(goodResult[0])

How to remove child by id and retrive the parent objects using filter

I am trying to filter the parent, by removing it's child id only by not matching. in case if there is no child exist, the parent should be removed.
I try like this, but not works.
var rm = 7;
var objects = [
{
name: "parent1",
id: 1,
blog: [
{
name: "child1",
id: 1
},
{
name: "child2",
id: 2
}
]
},
{
name: "parent2",
id: 2,
blog: [
{
name: "child3",
id: 3
},
{
name: "child4",
id: 4
}
]
},
{
name: "parent3",
id: 3,
blog: [
{
name: "child5",
id: 5
},
{
name: "child6",
id: 6
}
]
},
{
name: "parent4",
id: 3,
blog: [
{
name: "child6",
id: 7
}
]
},
]
var result = objects.filter(value => {
if(!value.blog) return;
return value.blog.some(blog => blog.id !== rm)
})
console.log(result);
What is wrong here, or some one show me the correct approach?
looking for :
need to remove the blog if the id is same as rm, parent with other children required to exist.
need to remove the parent, after remove the children, in case there is no child(blog) exist.
Live Demo
Loop through the list of parents, and inside that loop, try to remove blogs with the given id first. Once you have done that, you can check if the blogs property has became empty, and if so, filter it out:
// We're going to filter out objects with no blogs
var result = objects.filter(value => {
// First filter blogs that match the given id
value.blog = value.blog.filter(blog => blog.id !== rm);
// Then, if the new length is different than 0, keep the parent
return value.blog.length;
})
I think the below code is what you are looking for
var result = objects.map(value => {
const blog = value.blog.filter(blog => blog.id !== rm);
if(blog.length === 0) {
return;
}
value.blog = blog;
return value;
}).filter(item => item);
Demo: https://jsfiddle.net/7Lp82z4k/3/
var result = objects.map(parent => {
parent.blog = parent.blog.filter(child => child.id !== rm);
return parent}).filter(parent => parent.blog && parent.blog.length > 0);

Add array as element of another Array

I have an array like this
$scope.dogs = [
{ id: 1, breed: 'German Shepherd' },
{ id: 2, breed: 'Collie' }
]
And a second array like this:
$scope.owners = [
{ name: 'Mary', breedowned: 'German Shepherd' },
{ name: 'Bill', breedowned: 'German Shepherd' },
{ name: 'Bob', breedowned: 'Collie' }
]
I want to push the list of owners into the list of dogs like so basically creating:
$scope.dogs = [
{ id: 1, breed: 'German Shepherd', owners: [...] }
]
I tried to use forEach and push the owners into the dogs array, but it does not work.
angular.forEach($scope.dogs, function (value, key) {
for (x = 0; x < $scope.owners.length; x++) {
if ($scope.owners[i].breedowned == value.breed) {
$scope.dogs[key].owners.push($scope.owners[i])
}
}
});
Thanks for any help!
If you don't want any form of dependency, just use Array.prototype.push.apply, this way:
Array.prototype.push.apply($scope.owners, $scope.dogs);
You didnt mention any errors, but I see an issue with you missing var in front of the x in the for loop, and also owners is not initialized in the dog object. Here's a consistent nested loop solution:
angular.forEach($scope.dogs, function (dog) {
angular.forEach($scope.owners, function (owner) {
if (owner.breedowned == dog.breed) {
dog.owners = dog.owners || []
dog.owners.push(owner)
}
})
})
Here a better solution that only goes through the owners array once and only through the dogs array once.
var tracker = $scope.owners.reduce(function(trackerObj, owner){
var breedowned = owner.breedowned;
trackerObj[breedowned] = trackerObj[breedowned] || [];
trackerObj[breedowned].push(owner);
return trackerObj;
}, {});
$scope.dogs.forEach(function(dog){
dog.owners = tracker[dog.breed];
});

Categories