Remove duplicated objects according to one of their key - javascript

I have an array which has only objects in it and I would like to remove duplicated objects based one of their key value which is val.js.url but wanna make it remaining object the latest one among the duplicated objects so I basically used reverse() in my code`.
My array:
[
{
"id": "js_1oc3uiteki22",
"tab": {
"title": "title 1",
"url": "http://google.com"
},
"js": {
"initiator": "https://google.com",
"url": "http://url.com"
}
},
{
"id": "js_1oc3uiteki22",
"tab": {
"title": "title 2",
"url": "http://google2.com"
},
"js": {
"initiator": "https://google2.com",
"url": "http://url.com"
}
}
]
Expected result:
[
{
"id": "js_1oc3uiteki22",
"tab": {
"title": "title 2",
"url": "http://google2.com"
},
"js": {
"initiator": "https://google2.com",
"url": "http://url.com"
}
}
]
Actually I have this following code which solves this problem but when I need to use that code 2 times in same js file I guess it's kinda conflicts and doesn't clean the duplicates well in second array.
function dupfix(arr) {
return arr.reverse().filter(val => {
if (!this.hasOwnProperty(val.js.url)) {
return this[val.js.url] = true
}
return false
}, {}).reverse()
}
file = dupfix(file)
So, how can I fix that code above or is there any other better methods to do that? Thanks.

I found that one really fast among other alternatives,
https://stackoverflow.com/a/61027136
function removeDuplicates(array, key) {
let lookup = {};
array.forEach(element => {
lookup[element[key]] = element
});
return Object.keys(lookup).map(key => lookup[key]);
};
removeDuplicates(array,'objectKey');

You can use like this to filter the duplicates.
const myArr=[
{
"id": "js_1oc3uiteki22",
"tab": {
"title": "title 1",
"url": "http://google.com"
},
"js": {
"initiator": "https://google.com",
"url": "http://url.com"
}
},
{
"id": "js_1oc3uiteki22",
"tab": {
"title": "title 2",
"url": "http://google2.com"
},
"js": {
"initiator": "https://google2.com",
"url": "http://url2.com"
}
},
{
"id": "js_1oc3uiteki23",
"tab": {
"title": "title 3",
"url": "http://google3.com"
},
"js": {
"initiator": "https://google3.com",
"url": "http://url3.com"
}
},
{
"id": "js_1oc3uiteki23",
"tab": {
"title": "title 4",
"url": "http://google4.com"
},
"js": {
"initiator": "https://google4.com",
"url": "http://url4.com"
}
}
]
function removeDuplicates(arr) {
let uniqueIds = [];
var result = arr.slice().reverse().filter(item => {
var isDuplicate = uniqueIds.includes(item.id);
if (!isDuplicate) {
uniqueIds.push(item.id);
return item;
}
});
return result;
}
console.log(removeDuplicates(myArr));

You can use hash grouping to uniquely identify objects:
const val = [{"id":"js_1oc3uiteki22","tab":{"title":"title 1","url":"http://google.com"},"js":{"initiator":"https://google.com","url":"http://url.com"}},{"id":"js_1oc3uiteki22","tab":{"title":"title 2","url":"http://google2.com"},"js":{"initiator":"https://google2.com","url":"http://url.com"}}];
const uniqs = val.reduce((r, item) => (r[item.js.url] = item, r), {});
const result = Object.values(uniqs);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0 }

Related

Delete an object inside an array of objects by value

Having the following nested array of objects:
[
{
"items": [
{
"name": "See data",
"href": "/data",
},
{
"name": "Account",
"href": "/account",
"icon": {}
}
]
},
{
"items": [
{
"name": "name",
"href": "/name",
"icon": {}
},
{
"name": "My Rooms",
"href": "/rooms",
"icon": {}
}
]
},
{
"items": [
{
"name": "user",
"href": "/user",
"icon": {}
}
]
}
]
How it's possible to remove an inside object by name?
For example to remove the object with name "Account"?
A solution that works is delete myData[0].items[1]; but it's kind of hardcoded.
Also tried like:
myData[0].items = myData[0].items.filter(function (item) {
return item.name !== 'Account';
});
You can use splice to change the original array in-place and findIndex to find the index of the item to remove.
for (const {items} of data) {
const i = items.findIndex(({name}) => name === 'Account');
if (i > -1) items.splice(i, 1);
}

Compare Arrays and Remove Duplicates from the Final Array. Pokedex App

I create a Pokédex app, but i ran in some Problems with the double type Pokémon:
I call pokeapi twice to 2 endpoints (one for each Type), and i need to compare the Results in different Ways.
let a = {
"double_damage_from": [
{
"name": "ground",
"url": "https://pokeapi.co/api/v2/type/5/"
},
{
"name": "rock",
"url": "https://pokeapi.co/api/v2/type/6/"
},
{
"name": "water",
"url": "https://pokeapi.co/api/v2/type/11/"
}
],
"half_damage_from": [
{
"name": "bug",
"url": "https://pokeapi.co/api/v2/type/7/"
},
{
"name": "steel",
"url": "https://pokeapi.co/api/v2/type/9/"
},
{
"name": "fire",
"url": "https://pokeapi.co/api/v2/type/10/"
},
{
"name": "grass",
"url": "https://pokeapi.co/api/v2/type/12/"
},
{
"name": "ice",
"url": "https://pokeapi.co/api/v2/type/15/"
},
{
"name": "fairy",
"url": "https://pokeapi.co/api/v2/type/18/"
}
],
"no_damage_from": []
};
let b = {
"double_damage_from": [
{
"name": "fighting",
"url": "https://pokeapi.co/api/v2/type/2/"
},
{
"name": "ground",
"url": "https://pokeapi.co/api/v2/type/5/"
},
{
"name": "steel",
"url": "https://pokeapi.co/api/v2/type/9/"
},
{
"name": "water",
"url": "https://pokeapi.co/api/v2/type/11/"
},
{
"name": "grass",
"url": "https://pokeapi.co/api/v2/type/12/"
}
],
"half_damage_from": [
{
"name": "normal",
"url": "https://pokeapi.co/api/v2/type/1/"
},
{
"name": "flying",
"url": "https://pokeapi.co/api/v2/type/3/"
},
{
"name": "poison",
"url": "https://pokeapi.co/api/v2/type/4/"
},
{
"name": "fire",
"url": "https://pokeapi.co/api/v2/type/10/"
}
],
"no_damage_from": []
};
I need to Compare the Data and get the Matches in a array.
This works fine and i got the 4x, 1x, and 1/4x damage in a array:
getMatch(a, b) {
let matches = [];
for (let i = 0; i < a.length; i++) {
for (let e = 0; e < b.length; e++) {
if (a[i].name === b[e].name) matches.push(a[i]);
}
}
return matches;
}
compareTypes(a, b) {
let four_damage_from = this.getMatch(a.double_damage_from, b.double_damage_from);
let double_damage_from = [];
let normal_damage_from = this.getMatch(a.double_damage_from, b.half_damage_from);
let half_damage_from = [];
let quarter_damage_from = this.getMatch(a.half_damage_from, b.half_damage_from);
let no_damage_from = this.getMatch(a.no_damage_from, b.no_damage_from);
let matches = { four_damage_from, double_damage_from, normal_damage_from, half_damage_from, quarter_damage_from, no_damage_from };
return matches;
}
to find the correct types for double_damage_from i have to merge a.double_damage_from and b.double_damage_from e.g. to c.double_damage_from. then i have to remove from c.double_damage_from all types that are in four_damage_from, normal_damage_from, quarter_damage_from, no_damage_from to get the correct 2x types, the same with half_damage_from.
I tried many solution but i didn't figure out how to solve this.
greetings Raphi
It Works with lodash, i need to think a bit about but basically works.
removeMatch(union, remove, double = false) {
union = _.differenceBy(union, remove.four_damage_from, 'name');
union = _.differenceBy(union, remove.normal_damage_from, 'name');
union = _.differenceBy(union, remove.quarter_damage_from, 'name');
// union = _.differenceBy(union, remove.no_damage_from, 'name');
if(double) {
union = _.differenceBy(union, remove.half_damage_from, 'name');
} else {
union = _.differenceBy(union, remove.double_damage_from, 'name');
}
return union;
}

How do return the value of an attribute in a nested object without using the traditional js object navigation style?

For example how do I automatically loop through all "value" attributes in the object below without doing "tags.value" or "style.value"
[
{
"title": "Old Man's War",
"author": {
"name": "John Scalzi",
"tags": [
{
"value": "American"
}
]
}
},
{
"title": "The Lock Artist",
"author": {
"name": "Steve Hamilton",
"tags": [
{
"value": "English"
}
"style": [
{
"value": "Italix"
}
]
}
}
]
Were you looking to extract a list of all styles & tags? One direct way is through a reduce(), map() combo
let attributes = data.reduce((b, a) => ({
tags: [...b.tags, a.author.tags?.map(v => v.value) || []].flat(),
styles: [...b.styles, a.author.style?.map(v => v.value) || []].flat() }), {tags:[], styles:[]})
Output:
{
"tags": [
"American",
"English"
],
"styles": [
"Italix"
]
}
const data = [{
"title": "Old Man's War",
"author": {
"name": "John Scalzi",
"tags": [{
"value": "American"
}]
}
}, {
"title": "The Lock Artist",
"author": {
"name": "Steve Hamilton",
"tags": [{
"value": "English"
}],
"style": [{
"value": "Italix"
}]
}
}]
// just the tag values
let attributes = data.reduce((b, a) => ({
tags: [...b.tags, a.author.tags?.map(v => v.value) || []].flat(),
styles: [...b.styles, a.author.style?.map(v => v.value) || []].flat() }), {tags:[], styles:[]})
console.log(attributes)
//first,there is an error in your json.I assume it like this
const data = [
{
"title":"Old Man's War",
"author":{
"name":"John Scalzi",
"tags":[
{
"value":"American"
}
]
}
},
{
"title":"The Lock Artist",
"author":{
"name":"Steve Hamilton",
"tags":[
{
"value":"English"
}
],
"style":[
{
"value":"Italix"
}
]
}
}
]
for(const top of data){
if(typeof top == 'object'){
for(const second_key in top){
const second = top[second_key]
if(typeof second == 'object'){
for(const third_key in second){
const third = second[third_key]
if(Array.isArray(third)){
for(const fourth of third){
document.write(fourth['value']+"<br>")
}
}
}
}
}
}
}
//this is another solution
const data = [
{
"title":"Old Man's War",
"author":{
"name":"John Scalzi",
"tags":[
{
"value":"American"
}
]
}
},
{
"title":"The Lock Artist",
"author":{
"name":"Steve Hamilton",
"tags":[
{
"value":"English"
}
],
"style":[
{
"value":"Italix"
}
]
}
}
]
function lookForValue(obj){
if(obj.hasOwnProperty('value')){
document.write(obj['value']+"<br>")
return
}
if(typeof obj == 'object'){
for(const key in obj){
lookForValue(obj[key])
}
}
if(Array.isArray(obj)){
for(const item in obj){
lookForValue(item)
}
}
}
lookForValue(data)

Flatten arrays within object of arrays with data from parent object

I want to flatten some arrays nested in each object of an array of objects to return an array of objects with data from the parent objects. Quite a mouthful but perhaps some example json will help explain.
My current data and code is:
const galleries = [
{
"gallery": [
{
"url": "https://cdn.example.com/images/0e7f6dfeaade4b63ac4e18d25da3b32099c6a19f-1080x1080.jpg"
},
{
"url": "https://cdn.example.com/images/47688945188ac5788e29054b2be1fda95d474ea9-1080x1080.jpg"
},
{
"url": "https://cdn.example.com/images/a31b2ceec33211139918a21a75faaea914f47e39-1080x1080.jpg"
}
],
"slug": "stella-mccartney",
"title": "Stella McCartney"
},
{
"gallery": [
{
"url": "https://cdn.example.com/images/da8818751ed5f871ac3c48adc7211e30fa7e4e33-4555x5906.jpg"
},
{
"url": "https://cdn.example.com/images/0618ca397c55949629d04127519955796b6f7009-4426x5739.jpg"
}
],
"slug": "esquire",
"title": "Esquire"
},
{
"gallery": [
{
"url": "https://cdn.example.com/images/60e617f13cfe8314aa2fb1b90973792252011915-3000x1827.jpg"
},
{
"url": "https://cdn.example.com/images/c9c7443cad60078892fe536b8be27080e780e847-2400x3000.jpg"
}
],
"slug": "matches",
"title": "Matches"
},
{
"gallery": [
{
"url": "https://cdn.example.com/images/3b4be2e581ec8eb542bb4e77e2e7de8858ca3229-5339x3000.jpg"
}
],
"slug": "testing-project-2",
"title": "Testing Project 2"
}
]
const AllThumbnails = [].concat(
...galleries.map((gallery) => ({
image: gallery.gallery,
slug: gallery.slug,
}))
)
console.log(AllThumbnails)
My ideal output is:
[
{
"url": "https://cdn.example.com/images/0e7f6dfeaade4b63ac4e18d25da3b32099c6a19f-1080x1080.jpg",
"slug": "stella-mccartney"
},
{
"url": "https://cdn.example.com/images/47688945188ac5788e29054b2be1fda95d474ea9-1080x1080.jpg",
"slug": "stella-mccartney"
},
{
"url": "https://cdn.example.com/images/a31b2ceec33211139918a21a75faaea914f47e39-1080x1080.jpg",
"slug": "stella-mccartney"
},
{
"url": "https://cdn.example.com/images/da8818751ed5f871ac3c48adc7211e30fa7e4e33-4555x5906.jpg",
"slug": "esquire"
},
{
"url": "https://cdn.example.com/images/0618ca397c55949629d04127519955796b6f7009-4426x5739.jpg",
"slug": "esquire"
},
{
"url": "https://cdn.example.com/images/60e617f13cfe8314aa2fb1b90973792252011915-3000x1827.jpg",
"slug": "matches"
},
{
"url": "https://cdn.example.com/images/c9c7443cad60078892fe536b8be27080e780e847-2400x3000.jpg",
"slug": "matches"
},
{
"url": "https://cdn.example.com/images/3b4be2e581ec8eb542bb4e77e2e7de8858ca3229-5339x3000.jpg",
"slug": "testing-project-2",
}
]
How can I append the slug property correctly? Any help/pointers would be much appreciated.
You could use
const allThumbnails = galleries.map(parent =>
parent.gallery.map(g => ({url: g.url, slug: parent.slug}))).flat();
.map() will map each parent object to an array of {url, slug}, and then .flat() will flatten these nested arrays.
const galleries = [
{
"gallery": [
{
"url": "https://cdn.example.com/images/0e7f6dfeaade4b63ac4e18d25da3b32099c6a19f-1080x1080.jpg"
},
{
"url": "https://cdn.example.com/images/47688945188ac5788e29054b2be1fda95d474ea9-1080x1080.jpg"
},
{
"url": "https://cdn.example.com/images/a31b2ceec33211139918a21a75faaea914f47e39-1080x1080.jpg"
}
],
"slug": "stella-mccartney",
"title": "Stella McCartney"
},
{
"gallery": [
{
"url": "https://cdn.example.com/images/da8818751ed5f871ac3c48adc7211e30fa7e4e33-4555x5906.jpg"
},
{
"url": "https://cdn.example.com/images/0618ca397c55949629d04127519955796b6f7009-4426x5739.jpg"
}
],
"slug": "esquire",
"title": "Esquire"
},
{
"gallery": [
{
"url": "https://cdn.example.com/images/60e617f13cfe8314aa2fb1b90973792252011915-3000x1827.jpg"
},
{
"url": "https://cdn.example.com/images/c9c7443cad60078892fe536b8be27080e780e847-2400x3000.jpg"
}
],
"slug": "matches",
"title": "Matches"
},
{
"gallery": [
{
"url": "https://cdn.example.com/images/3b4be2e581ec8eb542bb4e77e2e7de8858ca3229-5339x3000.jpg"
}
],
"slug": "testing-project-2",
"title": "Testing Project 2"
}
];
const allThumbnails = galleries.map(parent => parent.gallery.map(g => ({url: g.url, slug: parent.slug}))).flat();
console.log(allThumbnails);
you can use reduce to do this
const galleries = [{
"gallery": [{
"url": "https://cdn.example.com/images/0e7f6dfeaade4b63ac4e18d25da3b32099c6a19f-1080x1080.jpg"
},
{
"url": "https://cdn.example.com/images/47688945188ac5788e29054b2be1fda95d474ea9-1080x1080.jpg"
},
{
"url": "https://cdn.example.com/images/a31b2ceec33211139918a21a75faaea914f47e39-1080x1080.jpg"
}
],
"slug": "stella-mccartney",
"title": "Stella McCartney"
},
{
"gallery": [{
"url": "https://cdn.example.com/images/da8818751ed5f871ac3c48adc7211e30fa7e4e33-4555x5906.jpg"
},
{
"url": "https://cdn.example.com/images/0618ca397c55949629d04127519955796b6f7009-4426x5739.jpg"
}
],
"slug": "esquire",
"title": "Esquire"
},
{
"gallery": [{
"url": "https://cdn.example.com/images/60e617f13cfe8314aa2fb1b90973792252011915-3000x1827.jpg"
},
{
"url": "https://cdn.example.com/images/c9c7443cad60078892fe536b8be27080e780e847-2400x3000.jpg"
}
],
"slug": "matches",
"title": "Matches"
},
{
"gallery": [{
"url": "https://cdn.example.com/images/3b4be2e581ec8eb542bb4e77e2e7de8858ca3229-5339x3000.jpg"
}],
"slug": "testing-project-2",
"title": "Testing Project 2"
}
]
const flatten = galleries.reduce((acc, curr) => {
curr.gallery.forEach(g => {
acc.push({
url: g.url,
slug: curr.slug
});
});
return acc;
}, []);
console.log(flatten);
Looks like I'm a little late with my answer, I think Kirill's solution is going to be the most practical one.
Here is my solution anyways:
let newArray = []
galleries.forEach(function (gallery) {
gallery["gallery"].forEach(function (url) {
newArray.push({"url": url["url"], "slug": gallery["slug"]})
})
})
Some of these answers are very close to mine, but here's mine using forEach with ES6 syntax, which in my opinion is more readable:
const allThumbnails = new Array();
thumbnails.forEach(set => {
set.galleries.forEach(item => {
allThumbnails.push({url: item.url, slug: set.slug};
});
});

how to return an array inside an array javascript

i have an array inside an array...how do i return all the values using a for loop in javascript/angular?
for example my json...
[
{
"Name": "element1",
"Attributes": [
{"file":"document.doc"},
{"file":"document2.doc"}
]
},
{
"Name": "element2",
"Attributes": [
{"file":"document3.doc"},
{"file":"document4.doc"}
]
},
{
"Name": "element3",
"Attributes": [
{"file":"document5.doc"},
{"file":"document6.doc"}
]
}
]
having a tough time just returning all the files within attributes...only seem to be getting the first one everytime.
EDIT:
what i have so far..
function getAllFiles() {
for (var i = 0; i < Attributes.file.length; i++) {
return Attributes.file[i];
}
}
One of the methods how to get the desired output, using Array#reduce.
var json = [{Name:"element1",Attributes:[{file:"document.doc"},{file:"document2.doc"}]},{Name:"element2",Attributes:[{file:"document3.doc"},{file:"document4.doc"}]},{Name:"element3",Attributes:[{file:"document5.doc"},{file:"document6.doc"}]}],
res = json.reduce(function(s,a){
s.push(...a.Attributes.map(c => c.file));
return s;
}, []);
console.log(res);
ES5
var json = [{Name:"element1",Attributes:[{file:"document.doc"},{file:"document2.doc"}]},{Name:"element2",Attributes:[{file:"document3.doc"},{file:"document4.doc"}]},{Name:"element3",Attributes:[{file:"document5.doc"},{file:"document6.doc"}]}],
res = json.reduce(function(s,a){
s = s.concat(a.Attributes.map(c => c.file));
return s;
}, []);
console.log(res);
try
var files = [];
json.forEach(function(obj) {
obj.Attributes.forEach(function (f) {
files.push(f.file); })
});
this loops on the json array then on each element's attributes then adds the vilue of file
You could show all the files using Array methods like map and reduce:
var data = [{
"Name": "element1",
"Attributes": [{
"file": "document.doc"
},
{
"file": "document2.doc"
}
]
},
{
"Name": "element2",
"Attributes": [{
"file": "document3.doc"
},
{
"file": "document4.doc"
}
]
},
{
"Name": "element3",
"Attributes": [{
"file": "document5.doc"
},
{
"file": "document6.doc"
}
]
}
];
var files = data.map(function (obj) {
return obj.Attributes.map(function (i) {
return i.file;
});
}).reduce(function (x, y) {
return x.concat(y);
});
console.log(files);
Although Kind user's answer is better:
var data = [{
"Name": "element1",
"Attributes": [{
"file": "document.doc"
},
{
"file": "document2.doc"
}
]
},
{
"Name": "element2",
"Attributes": [{
"file": "document3.doc"
},
{
"file": "document4.doc"
}
]
},
{
"Name": "element3",
"Attributes": [{
"file": "document5.doc"
},
{
"file": "document6.doc"
}
]
}
];
var files = data.reduce(function(acc, val) {
return acc.concat(
val.Attributes.map(function(attribute) {
return attribute.file;
})
);
}, []);
console.log(files);
I renamed some variables so that the code makes more sense (to me).
Something like outerArray.innerArray. in your case arrayName.Attributes should work.

Categories