Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 4 years ago.
Improve this question
I have this below JSON array. In this, I want to find the common item object and add it to another list and remove that from the source list.
The item with id is common for two objects. Also, the list is dynamic.
[
{
"id": 1,
"item": {
"id": 1,
"name": "itemA"
}
},
{
"id": 2,
"item": {
"id": 1,
"name": "itemA"
}
},
{
"id": 3,
"item": {
"id": 2,
"name": "itemB"
}
}
]
You could use reduce in combination with a Map for keying your data:
const data = [ { "id": 1, "item": { "id": 1, "name": "itemA" } }, { "id": 2, "item": { "id": 1, "name": "itemA" } }, { "id": 3, "item": { "id": 2, "name": "itemB" } } ];
const [map, dupes] = data.reduce(([map, dupes], obj) =>
map.has(obj.item.id) ? [map, dupes.concat(obj)] : [map.set(obj.item.id, obj), dupes]
, [new Map, []]);
const uniques = [...map.values()];
console.log(uniques);
console.log('dupes:');
console.log(dupes);
After reading your comments, it seems you want to reject anything that has a duplicate, so not even keeping one original. So then the code could be:
const data = [ { "id": 1, "item": { "id": 1, "name": "itemA" } }, { "id": 2, "item": { "id": 1, "name": "itemA" } }, { "id": 3, "item": { "id": 2, "name": "itemB" } } ];
const map = new Map(data.map(obj => [obj.item.id, []]));
data.forEach(obj => map.get(obj.item.id).push(obj));
const uniques = [].concat(...[...map.values()].filter(arr => arr.length === 1));
const dupes = [].concat(...[...map.values()].filter(arr => arr.length > 1));
console.log(uniques);
console.log('dupes:');
console.log(dupes);
Array.reduce over your Array, passing an accumulator.
Accumulator keeps track of found elements.
Check accumulator if iterated element was previously found by id, if yes push it into duplicates.
Otherwise push it into arr.
const arr = [
{
"id": 1,
"item": {
"id": 1,
"name": "itemA"
}
},
{
"id": 2,
"item": {
"id": 1,
"name": "itemA"
}
},
{
"id": 3,
"item": {
"id": 2,
"name": "itemB"
}
}
]
const result = arr.reduce((acc, el, i) => {
if (acc.found[el.item.id]) {
acc.duplicates.push(el)
} else {
acc.source.push(el)
}
acc.found[el.item.id] = true
if (i === arr.length - 1)
delete acc.found
return acc
}, {
source: [],
duplicates: [],
found: {}
})
console.log(result.source) // source with removed duplicates
console.log(result.duplicates) // array of duplicates
Related
This question already has answers here:
How to remove all duplicates from an array of objects?
(77 answers)
Closed 4 months ago.
If the 'id' key is duplicated among the objects in the array, how to delete the object
I tried using filter, map, and set, but it doesn't work.
It's not a one-dimensional array, so I don't know how to do it.
as-is
"category": {
"key": 1,
"order": 1,
"list": [
{
"id": "12345",
...
},
{
"id": "12345",
...
},
{
"id": "67890",
...
},
]
}
to-be
"category": {
"key": 1,
"order": 1,
"list": [
{
"id": "12345",
...
},
{
"id": "67890",
...
},
]
}
We iterate over that list using reduce function, then we checked whether the key we are accessing is visited or not with keys parameter of reduce method, and if it's not visited then we just push that object to a filtered array and returning keys array to keep it updated.
const data = {
"category": {
"key": 1,
"order": 1,
"list": [{
"id": "12345"
},
{
"id": "12345"
},
{
"id": "67890"
},
]
}
}
let filtered = [];
data.category.list.reduce((keys, currentObject) => {
if (!keys.includes(currentObject.id)) { //checking if current oject id is present in keys or not
// if not present than we will just push that object in
keys.push(currentObject.id);
//getting filttered object
filtered.push(currentObject);
}
return keys; //returning keys to update it
}, [])
data.category.list = filtered; //updating list
console.log(data);
A solution based on #Nick's comment
let data ={
"category": {
"key": 1,
"order": 1,
"list": [
{
"id": "12345"
},
{
"id": "12345"
},
{
"id": "67890"
},
]
}
}
let uniq = data.category.list.filter((o,i,a) => a.findIndex(o2 => o2.id == o.id) == i)
data.category.list = uniq
console.log(data)
You can use a set to track if id
const category = [{
"category": {
"key": 1,
"order": 1,
"list": [{
"id": "12345",
},
{
"id": "12345",
},
{
"id": "67890",
},
]
}
}]
const z = category.map(elem => {
const set = new Set()
return {
...elem,
category: {
...elem.category,
list: elem.category.list.reduce((acc, curr) => {
if (!set.has(curr.id)) {
set.add(curr.id);
acc.push(curr)
}
return acc;
}, [])
}
}
});
console.log(z)
I'm trying to filter some objects based on another array of objects. So I'm getting data from an API. These are for example receipts:
[
{
"id": 1,
"name": "test",
"category": {
"id": 1,
"name": "Cookies",
},
},
{
"id": 2,
"name": "test2",
"category": {
"id": 2,
"name": "Candy",
},
}
]
Then I'm trying to filter the objects on the category name based on another array of categories.
I've created a function for this:
function onSelectCategory(category) {
let receiptsList = receipts.filter((a) =>
a.category.includes(category.name)
);
setReceiptsView(receiptsList);
setSelectedCategory(category);
}
const category = [ { "id": 2, "name": "Candy" } ];
onSelectCategory(category);
When I run this function, I get an empty Array []. I can't really figure out what I'm doing wrong.
Since the param seems to be an array of objects, you need to use Array#some for comparison instead:
const receipts = [
{ "id": 1, "name": "test", "category": { "id": 1, "name": "Cookies" } },
{ "id": 2, "name": "test2", "category": { "id": 2, "name": "Candy" } }
];
const categories = [ { "id": 2, "name": "Candy" } ];
const receiptsList = receipts.filter(({ category }) =>
categories.some(({ name }) => name === category.name)
);
console.log(receiptsList);
Another solution using Set:
const receipts = [
{ "id": 1, "name": "test", "category": { "id": 1, "name": "Cookies" } },
{ "id": 2, "name": "test2", "category": { "id": 2, "name": "Candy" } }
];
const categories = [ { "id": 2, "name": "Candy" } ];
const categorySet = new Set(categories.map(({ name }) => name));
const receiptsList = receipts.filter(({ category }) =>
categorySet.has(category.name)
);
console.log(receiptsList);
Assuming that category (the parameter) is a string, the issue is that you are attempting to get the attribute name from the string, when you should be comparing the string to the object.
Try this:
a.category.name == category;
instead of
a.category.includes(category.name)
I may be wrong aboout assuming that category is a string, please clarify by telling us what the parameter category is equal to.
How can I assign key value from array of object to another array object
I would like to assign the key:value pair to the existing array of object from the another array of objects.
I have check this thread but it is not working in my case.
I have tried something like this but that is not returning the desired output that I am looking for.
const DataA = {
"id": 57,
"status": true,
"options": [{ "id": 1, "name": "Type A" },
{ "id": 2, "name": "Type B" },
{ "id": 3, "name": "Type C" }]
}
const DataB = {
"id": 57,
"status": true,
"options": [{ "id": 1, "value": 10 },
{ "id": 2, "value": 20 },
{ "id": 3, "value": 30 }]
}
let result;
var A1 = DataA.options.map((v) => {
console.log(v);
result = v;
})
var A2 = DataB.options.map(v => {
result.options = v;
console.log("result",result);
})
let arr3 = DataA.options.map((item, i) => Object.assign({}, item, DataB[i]));
console.log(arr3);
Result will be I need as below:
const DataA = {
"id": 57,
"status": true,
"options": [{ "id": 1, "name": "Type A", "value": 10 },
{ "id": 2, "name": "Type B", "value": 20 },
{ "id": 3, "name": "Type C", "value": 30 }]
}
I need to merge the deep clone of the array that is slightly different from this thread.
The linked duplicate does actually address your question, but you need to adjust it to your situation and not just copy paste.
DataA.options = DataA.options.map((item, i) => Object.assign({}, item, DataB.options[i]));
but since this mutates the original DataA object anyway, you may as well just use forEach() and avoid creating the intermediate array from .map().
DataA.options.forEach((item, i) => Object.assign(item, DataB.options[i]));
Both of the above assume that the options arrays of both objects are a. of the same length, and b. sorted by id. To avoid these assumptions you can use .find() to look for matching elements instead of relying on index.
DataA.options.forEach(item =>
Object.assign(item, DataB.options.find(({ id }) => id === item.id)));
const DataA = {
"id": 57,
"status": true,
"options": [
{ "id": 1, "name": "Type A" },
{ "id": 2, "name": "Type B" },
{ "id": 3, "name": "Type C" }]
}
const DataB = {
"id": 57,
"status": true,
"options": [
{ "id": 1, "value": 10 },
{ "id": 2, "value": 20 },
{ "id": 3, "value": 30 }]
}
DataA.options.forEach(item =>
Object.assign(item, DataB.options.find(({ id }) => id === item.id)));
console.log(DataA)
.as-console-wrapper { max-height: 100% !important; top: 0; }
This question already has answers here:
How to map more than one property from an array of objects [duplicate]
(7 answers)
Closed 2 years ago.
I want to delete all element getData because It always same value. I try to use filter method to remove them
Here is my data
let data = [
{
"id": 3,
"employee_id": 2290,
"getData": {
"id": 9070
},
},
{
"id": 4,
"employee_id": 2291,
"getData": {
"id": 9070
},
}
]
Here is what I do
data = data.filter(item => {
return item.getData != null;
});
Here is what I want
let data = [
{
"id": 3,
"employee_id": 2290,
},
{
"id": 4,
"employee_id": 2291,
}
]
Is filter is the best way to remove this if not please give me some advice thanks
Filter is used to filter out items from an array the more suited ways for doing what you want to achieve is map() or forEach(). Below is a demo that can help you.
Also to remove a property form an object use delete operator
let data = [
{
"id": 3,
"employee_id": 2290,
"getData": {
"id": 9070
},
},
{
"id": 4,
"employee_id": 2291,
"getData": {
"id": 9070
},
}
]
data.map((item)=>{delete item.getData});
console.log(data);
let data2 = [
{
"id": 3,
"employee_id": 2290,
"getData": {
"id": 9070
},
},
{
"id": 4,
"employee_id": 2291,
"getData": {
"id": 9070
},
}
]
data2.forEach((item)=>{delete item.getData});
console.log(data);
Hope this help :)
$.each(data,function(i,e){delete data[i]["getData"];})
OR
$.grep(data,function(e,i){delete data[i]["getData"];})
Filter is to remove items from an array, not to remove properties from an object inside an array. You should use the map function.
let data = [
{
"id": 3,
"employee_id": 2290,
"getData": {
"id": 9070
},
},
{
"id": 4,
"employee_id": 2291,
"getData": {
"id": 9070
},
}
]
let output = data.map(({id, employee_id}) => ({ id, employee_id }));
console.log(output)
I'm trying to filter an array of objects where the filter is another array (of integers) which are values of properties of the first array. I've managed to make it work but I'm not sure if it's the best way. Since I'm a beginner in javascript, I'd appreciate any suggestions/improvements.
The items.json file contains an object with an array of objects. I want to filter all the objects (within that array) that have an id equal to the "ids" on the itemsids array.
code:
const itemsall = require('./items.json');
let itemsids = [1, 403, 3];
let filtereditems = [];
itemsids.forEach(id => {
itemsall.items.forEach(item => {
if (id === item.id) {
filtereditems.push(item);
}
});
});
items.json (a small part of it)
{
"items": [
{
"id": 0,
"name": "Egg",
"img": "http://www.serebii.net/pokemongo/items/egg.png"
},
{
"id": 1,
"name": "Pokeball",
"img": "http://www.serebii.net/pokemongo/items/20pokeballs.png"
},
{
"id": 2,
"name": "Greatball",
"img": "http://www.serebii.net/pokemongo/items/greatball.png"
}
]
}
output: (expected)
[
{
"id": 0,
"name": "Egg",
"img": "http://www.serebii.net/pokemongo/items/egg.png"
},
{
"id": 403,
"name": "Cool Incense",
"img": "http://www.serebii.net/pokemongo/items/incense.png"
},
{
"id": 3,
"name": "Ultraball",
"img": "http://www.serebii.net/pokemongo/items/ultraball.png"
}
]
Thanks!
You can use filter() and indexOf() to return filtered array.
var data = {
"items": [{
"id": 0,
"name": "Egg",
"img": "http://www.serebii.net/pokemongo/items/egg.png"
}, {
"id": 1,
"name": "Pokeball",
"img": "http://www.serebii.net/pokemongo/items/20pokeballs.png"
}, {
"id": 2,
"name": "Greatball",
"img": "http://www.serebii.net/pokemongo/items/greatball.png"
}]
}
let itemsids = [1, 403, 3];
var result = data.items.filter(function(e) {
return itemsids.indexOf(e.id) != -1
})
console.log(result)
With ES6/ES7 you can use includes() like this.
var result = data.items.filter((e) => itemsids.includes(e.id));