I am looking for the way to remove duplicates. I found a common way is to create a Set and then spread into a new Array.
How could I Set to acomplish this purpose? For instance, I have the following code:
const tmp1=[];
const tmp2=[{
guid:"e695d848-7188-4741-9c95-44bec634940f",
name: "Spreading.pdf",
code: "G1"
}];
const tmp = [...new Set([...tmp1],[...tmp2])]; //This should remove duplicates, but gets empty array
const x = [...tmp1, ...tmp2]; // This would keep duplicates
The issue is that because tmp1 is an empty array, then I am getting empty result. However, if I do the following, then getting correct result:
const tmp = [...new Set(...tmp1,[...tmp2])];
I think something is missing in here.
This is an example of duplicated entries where Set is working like a charm just keeping one record:
const tmp1=[{
guid:"e695d848-7188-4741-9c95-44bec634940f",
name: "Spreading.pdf",
code: "G1"
}];
const tmp2=[{
guid:"e695d848-7188-4741-9c95-44bec634940f",
name: "Spreading.pdf",
code: "G1"
}];
const tmp = [...new Set([...tmp1],[...tmp2])];
This was the original idea, but how about if one of the lists is empty. Then, I am getting an empty array if this occurs.
Thank you
Set should take 1 argument but it's taking 2, merge them into one:
const tmp = [...new Set([...tmp1, ...tmp2])];
Note: that this method won't remove duplicates because you are passing an object to the set and not a reference for it, in this case, you can do this instead:
const tmp1 = [];
const tmp2 = [{
guid: "e695d848-7188-4741-9c95-44bec634940f",
name: "Spreading.pdf",
code: "G1"
},
{
guid: "e695d848-7188-4741-9c95-44bec634940f",
name: "Spreading.pdf",
code: "G1"
}
];
// pass a special unique key that differs object from each other to item, in this case i passed guid
const tmp = [...new Map([...tmp1, ...tmp2].map(item => [item['guid'], item])).values()]
Just to explain why this example in the question seemingly work:
const tmp1=[{
guid:"e695d848-7188-4741-9c95-44bec634940f",
name: "Spreading.pdf",
code: "G1"
}];
const tmp2=[{
guid:"e695d848-7188-4741-9c95-44bec634940f",
name: "Spreading.pdf",
code: "G1"
}];
const tmp = [...new Set([...tmp1],[...tmp2])];
It results in one object because Set() only take one iterable object, so it takes the first one.
If const tmp2=[1, 2, 3] in the above example, tmp will still result in the one object in tmp1.
More about Set()
Related
let newValues = user.info.socialMedia ? [...user.info.socialMedia] : []
So here we get several objects into the array that have an id key, and instead of the objects themselves I want to have only the id strings in this array. How can I get this working? I am quite new to Javascript, so it would be nice to get some help here.
I tried a for of then a for in loop to get the ids out of there and push them to the array, tho this does not work for my case.
instead of the objects themselves I want to have only the id strings
That sounds like a .map() operation, to project one array into another by applying a transformation to each object. Something like this:
let newValues = user.info.socialMedia ? user.info.socialMedia.map(s => s.id) : []
Or perhaps simpler:
let newValues = user.info.socialMedia?.map(s => s.id) ?? []
For example:
let user = {
info: {
socialMedia: [
{ id: 1, name: 'Ron' },
{ id: 2, name: 'Tammy' },
{ id: 3, name: 'Tammy 2' }
]
}
};
let newValues = user.info.socialMedia?.map(s => s.id) ?? []
console.log(newValues);
Hello I'm trying to create an object that includes under the same property name a bunch of array values,
This what I'm trying
const quiz = [
{question: 'Who is the main character of DBZ',
options: ['Vegetta','Gohan','Goku']}
]
const newObj = {
options: []
}
quiz.forEach((item)=>{
item.options.forEach((item, index)=>{
newObj.options[`name${index}`] = item
})
})
expected value =
newObj = {
options: [{name: 'Vegetta'},{name:'Gohan'},{name:'Goku'}]
}
actual value received =
newObj = {
{ options: [ name0: 'Vegetta', name1: 'Gohan', name2: 'Goku' ] }}
Thanks in advance!
As you've noticed, newObj.options[`name${index}`] = item creates a new key on your options array, and sets that to item. You instead want to push an object of the form {name: item} into your array. There are a few ways you could go about this, one way is to use .push() like so:
quiz.forEach((item)=>{
item.options.forEach((item)=>{
newObj.options.push({name: item});
})
});
while not as common, you can also use set the current index of options, which is slightly different to the above example, as it will maintain the same index, which can be important if quiz is a sparse array that you want to keep the same indexing of on options:
quiz.forEach((item)=>{
item.options.forEach((item, index)=>{
newObj.options[index] = {name: item};
})
});
Example of the difference:
const arr = [1, 2,,,5]; // sparse array
const pushRes = [];
const indxRes = [];
arr.forEach(n => pushRes.push(n));
arr.forEach((n, i) => indxRes[i] = n);
console.log("Push result", pushRes);
console.log("Index result", indxRes);
For a different approach, you also have the option of using something like .flatMap() and .map() to create your options array, which you can use to create newObj:
const quiz = [
{question: 'Who is the main character of DBZ',
options: ['Vegetta','Gohan','Goku']}
];
const options = quiz.flatMap(({options}) => options.map(name => ({name})));
const newObj = {options};
console.log(newObj);
I had a lists of duplicate array of String and array of object. I want to find the property into one particular object of array uniquely without duplication of array object.
If can done in lodash library, it would be awesome.
const arr1 = ['test#email', 'test2#email']
const arr2 = [{ id: 1, email: 'test#email' }]
Expected result
['test2#email']
this is what I done so far
By turning arr1 into object frist so I can compare with arr2
const emailLists = _.map(arr, function (item) {
console.log(item)
return { email: item }
})
then merge them to together and used uniq to remove duplicates
const merge = _.unionBy(array1, array2, 'email')
const result _.uniq(merge, 'email');
I think it still not a good process and not clean
You can do it without lodash
const arr1 = ['test#email', 'test2#email']
const arr2 = [{ id: 1, email: 'test#email' }]
const emailToDelete = arr2.map(a => a.email)
const result = arr1.filter(e => !emailToDelete.includes(e))
console.log(result)
You can use lodash chain to solve that:
const result = _([...arr1, ...arr2.map(i => i.email)]) // ['test#email', 'test2#email', 'test#email']
.countBy() // { test#email: 2, test2#email: 1 }
.pickBy(count => count === 1) // { test2#email: 1 }
.keys() // ['test2#email']
.value();
You can use filter on the first array and check that an email address matches with some of your objects in the second array. So even if it matches with multiple objects, the matching email will only be in the output once.
I want to find the property into one particular object of array uniquely without duplication of array object
So then your expected output is wrong, as you provide an email that is not found in the object array. I guess that was a typo in your question.
const arr1 = ['test#email', 'test2#email']
const arr2 = [{ id: 1, email: 'test#email' }]
const result = arr1.filter(search => arr2.some(({email}) => email == search));
console.log(result);
Hello so i have array of objects something like this
const old = [{id: 1, name: 'Random'}, {id: 2, name: 'Random2'}]
also i have array
const wantedField = ['id']
So looking this result, i need values only for certain key
const finally = [[1],[2]]
I have tried something like this but not luck. End result should be array of arrays with just certain values.
old.map((obj, value) => {
const key = Object.keys(obj)[value]
if(wantedField.includes(const)) {
const newArray = []
const key = Object.keys(obj)[value]
newArray.push(obj[key])
return [newArray]
}
})
So this return [newArray] is wrong should return multiple values not just one. Please help regards.
This is a one-liner, with two nested maps. One to iterate over the input array, and another to iterate over the wanted field(s):
const old = [{id: 1, name: 'Random'}, {id: 2, name: 'Random2'}];
const wantedField = ['id'];
const result = old.map(o => wantedField.map(k => o[k]));
console.log(result);
Okay, so I am trying to create a function that allows you to input an array of Objects and it will return an array that removed any duplicate objects that reference the same object in memory. There can be objects with the same properties, but they must be different in-memory objects. I know that objects are stored by reference in JS and this is what I have so far:
const unique = array => {
let set = new Set();
return array.map((v, index) => {
if(set.has(v.id)) {
return false
} else {
set.add(v.id);
return index;
}
}).filter(e=>e).map(e=>array[e]);
}
Any advice is appreciated, I am trying to make this with a very efficient Big-O. Cheers!
EDIT: So many awesome responses. Right now when I run the script with arbitrary object properties (similar to the answers) and I get an empty array. I am still trying to wrap my head around filtering everything out but on for objects that are referenced in memory. I am not positive how JS handles objects with the same exact key/values. Thanks again!
Simple Set will do the trick
let a = {'a':1}
let b = {'a': 1,'b': 2, }
let c = {'a':1}
let arr = [a,b,c,a,a,b,b,c];
function filterSameMemoryObject(input){
return new Set([...input])
}
console.log(...filterSameMemoryObject(arr))
I don't think you need so much of code as you're just comparing memory references you can use === --> equality and sameness .
let a = {'a':1}
console.log(a === a ) // return true for same reference
console.log( {} === {}) // return false for not same reference
I don't see a good reason to do this map-filter-map combination. You can use only filter right away:
const unique = array => {
const set = new Set();
return array.filter(v => {
if (set.has(v.id)) {
return false
} else {
set.add(v.id);
return true;
}
});
};
Also if your array contains the objects that you want to compare by reference, not by their .id, you don't even need to the filtering yourself. You could just write:
const unique = array => Array.from(new Set(array));
The idea of using a Set is nice, but a Map will work even better as then you can do it all in the constructor callback:
const unique = array => [...new Map(array.map(v => [v.id, v])).values()]
// Demo:
var data = [
{ id: 1, name: "obj1" },
{ id: 3, name: "obj3" },
{ id: 1, name: "obj1" }, // dupe
{ id: 2, name: "obj2" },
{ id: 3, name: "obj3" }, // another dupe
];
console.log(unique(data));
Addendum
You speak of items that reference the same object in memory. Such a thing does not happen when your array is initialised as a plain literal, but if you assign the same object to several array entries, then you get duplicate references, like so:
const obj = { id: 1, name: "" };
const data = [obj, obj];
This is not the same thing as:
const data = [{ id: 1, name: "" }, { id: 1, name: "" }];
In the second version you have two different references in your array.
I have assumed that you want to "catch" such duplicates as well. If you only consider duplicate what is presented in the first version (shared references), then this was asked before.