How to merge/combine array of objects based on duplicate keys? - javascript

I am trying to merge data on any duplicate key but also rewrite the data object.
I am trying to merge the array of values depending on if each object has the same 'time'. After which, I would like to pair each value within the items with the name.
I think the easiest way to show is through the raw data I hope to transform, So I would like to transform the following;
var data = [{
"item": ["1", "2"],
"time": "12-15",
"name": "ben"
}, {
"item": ["3", "4"],
"time": "12-15",
"name": "bill"
}, {
"item": ["1", "2", "3"],
"time": "15-18",
"name": "ben"
}, {
"item": ["4", "5", "6"],
"time": "15-18",
"name": "bill"
}];
Into
var result = [{
"time": "12-15",
"ben": ["1", "2"],
"bill": ["3", "4"]
},
{
"time": "15-18",
"ben": ["1", "2", "3"],
"bill": ["4", "5", "6"]
}]
I have been trying to this this question to help me do this however I'm not getting very far. I cannot seem to resolve the issue of the first item that is checked not being output as an array.
Any help is much appreciated!
var data = [{
"item": ["1", "2"],
"time": "12-15",
"name": "ben"
}, {
"item": ["3", "4"],
"time": "12-15",
"name": "bill"
}, {
"item": ["1", "2", "3"],
"time": "15-18",
"name": "ben"
}, {
"item": ["4", "5", "6"],
"time": "15-18",
"name": "bill"
}];
var seen = {};
var result = data.filter(function(entry) {
var previous;
// Have we seen this label before?
if (seen.hasOwnProperty(entry.time)) {
// Yes, grab it and add this data to it
previous = seen[entry.time];
previous.item.push(entry.item);
// Don't keep this entry, we've merged it into the previous one
return false;
}
//console.log(seen)
// entry.data probably isn't an array; make it one for consistency
if (!Array.isArray(entry.item)) {
entry.item = [entry.item];
}
// Remember that we've seen it
seen[entry.time] = entry;
// Keep this one, we'll merge any others that match into it
return true;
});
console.log(result)

You could use a hash table for grouping.
var data = [{ "item": ["1", "2"], "time": "12-15", "name": "ben" }, { "item": ["3", "4"], "time": "12-15", "name": "bill" }, { "item": ["1", "2", "3"], "time": "15-18", "name": "ben" }, { "item": ["4", "5", "6"], "time": "15-18", "name": "bill" }],
result = [];
data.forEach(function (a) {
if (!this[a.time]) {
this[a.time] = { time: a.time };
result.push(this[a.time]);
}
this[a.time][a.name] = (this[a.time][a.name] || []).concat(a.item);
}, Object.create(null));
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Or with ES6 you could use a Map.
var data = [{ "item": ["1", "2"], "time": "12-15", "name": "ben" }, { "item": ["3", "4"], "time": "12-15", "name": "bill" }, { "item": ["1", "2", "3"], "time": "15-18", "name": "ben" }, { "item": ["4", "5", "6"], "time": "15-18", "name": "bill" }],
map = new Map,
result = [];
data.forEach(a => {
var o = map.get(a.time);
if (!o) {
o = { time: a.time };
map.set(a.time, o);
result.push(o);
}
o[a.name] = (o[a.name] || []).concat(a.item);
});
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

I would like to follow this approach creating two functions and returning a new object with the merged data, this way you avoid the mutation of your original object.
Note: this uses ES6 syntax but you can easily transform this code into ES5.
const data = [{
"item": ["1", "2"],
"time": "12-15",
"name": "ben"
}, {
"item": ["3", "4"],
"time": "12-15",
"name": "bill"
}, {
"item": ["1", "2", "3"],
"time": "15-18",
"name": "ben"
}, {
"item": ["4", "5", "6"],
"time": "15-18",
"name": "bill"
}];
// Get a list of unique times
const getTimes = data => data.reduce((a, c) => {
if (!a.includes(c.time)) {
a.push(c.time);
}
return a;
}, []);
// Merge the data into a single list using the times list as index
const mergeData = (data, times) => times.map(time => {
const obj = {};
obj.time = time;
data.forEach(record => {
if (record.time === time) {
obj[record.name] = record.item;
}
});
return obj;
});
const times = getTimes(data);
const result = mergeData(data, times);
console.log(result);

You can do it just with map() and filter() plus an inner loop like this :
var data = [{
"item": ["1", "2"],
"time": "12-15",
"name": "ben"
}, {
"item": ["3", "4"],
"time": "12-15",
"name": "bill"
}, {
"item": ["1", "2", "3"],
"time": "15-18",
"name": "ben"
}, {
"item": ["4", "5", "6"],
"time": "15-18",
"name": "bill"
}];
var skel = data.map(x => x.time).filter((x,i,arr) => arr.indexOf(x) === i).map(x => ({"time" : x}));
var result = skel.map(x => {
data.forEach(y => {
if(x.time === y.time)
x[y.name] = y.item;
})
return x;
} )
console.log(result);

You may do as follows;
var data = [{
"item": ["1", "2"],
"time": "12-15",
"name": "ben"
}, {
"item": ["3", "4"],
"time": "12-15",
"name": "bill"
}, {
"item": ["1", "2", "3"],
"time": "15-18",
"name": "ben"
}, {
"item": ["4", "5", "6"],
"time": "15-18",
"name": "bill"
}],
interim = data.reduce((h,d) => (h[d.time] = h[d.time] ? h[d.time].concat({[d.name]: d.item})
: [{[d.name]: d.item}],h),{}),
result = Object.keys(interim)
.map(k => Object.assign({time: k},...interim[k]));
console.log(result);

It might be helpful to write a function to group stuff by time:
class DefaultMap extends Map {
constructor(defaultConstructor) {
super();
this.defaultConstructor = defaultConstructor;
}
get(key) {
if (this.has(key)) {
return super.get(key);
}
const def = this.defaultConstructor();
this.set(key, def);
return def;
}
}
function groupBy(collection, key) {
const groups = new DefaultMap(() => []);
for (const item of collection) {
const itemKey = key(item);
const group = groups.get(itemKey);
group.push(item);
}
return groups;
}
Then you can just:
const result =
groupBy(data, entry => entry.time).entries().map(
([time, entries]) => {
const group = {time};
entries.forEach(entry => {
group[entry.name] = entry.item;
});
return group;
}
);

Try this
var timeGroup = _.groupBy(data,"time");
_.mapObject(timeGroup,function(val,key){
var benArray = _.flatten(_.values(_.pick(_.findWhere(val, {name:"ben"}),"item")));
var billArray = _.flatten(_.values(_.pick(_.findWhere(val,{name:"bill"}),"item")));
console.log({"time" : key,"ben" : benArray , "bill" : billArray })
})

Related

Filter an array of objects by another object of filters

I have an array of objects who follow this structure below:
{
"level": 1
"objectId": "3756"
"objectIdNo": 35636
"wpId": "3635473"
}
I now want to filter an array of these objects by another object. This filterObject would have the structure below:
// filterObject
{
level: "2"
objectId: "10"
wpId: "1"
}
But this filterObject doesn't always have all the key-value pairs because they get set manually in the UI. As a result the filterObject can also look like this:
{
level: "2"
}
My goal is to return a new array of filteredObjects who match this filterObject. When only one filter exists on the filterObject I want to return all objects that match this one key-value pair. But if more filters exist on the filterObject I want to return all objects that match both key-value pairs (not only one).
Example:
This is the data I want to filter:
[
{
"level": "1"
"objectId": "11"
"objectIdNo": "320"
"wpId": "123"
},
{
"level": "2"
"objectId": "12"
"objectIdNo": "321"
"wpId": "123"
},
{
"level": "2"
"objectId": "13"
"objectIdNo": "322"
"wpId": "120"
},
]
1.
If this is my filterObject:
{
"level": "2"
}
Return:
[
{
"level": "2"
"objectId": "12"
"objectIdNo": "321"
"wpId": "123"
},
{
"level": "2"
"objectId": "13"
"objectIdNo": "322"
"wpId": "120"
},
]
2.
If this is my filterObject:
{
"level": "2",
"wpId": "123"
}
Return:
[
{
"level": "2"
"objectId": "12"
"objectIdNo": "321"
"wpId": "123"
},
]
I hope that explains the logic I want to achieve which I couldn't implement myself. I would appreciate some ideas or applicable functions.
This is what I already tried in React. The data variable holds the array of objects and the filter variable hold the filterObjects.
useEffect(() => {
if (data) {
const filtered = data.filter((task) => {
if (!filter) {
return true;
}
return (
task.level === filter.level ||
task.objectId === filter.objectId ||
task.wpId === filter.wpId
);
});
setFilteredTasks(filtered);
}
}, [filter]);
With my attempt, if I just set the one filter key-value pair I get an empty array,
You can achieve this result using filter, Object.keys, and every.
You have to use filter and pass predicate that tell whether it is included in the final result.
In predicate, loop over all properties on the filters object and match if it is present in data or not. Simple
data.filter((o) =>Object.keys(filters).every((k) => filters[k] === o[k]));
const data = [{
level: "1",
objectId: "11",
objectIdNo: "320",
wpId: "123",
},
{
level: "2",
objectId: "12",
objectIdNo: "321",
wpId: "123",
},
{
level: "2",
objectId: "13",
objectIdNo: "322",
wpId: "120",
},
];
const filters = {
level: "2",
wpId: "123",
};
const result = data.filter((o) =>
Object.keys(filters).every((k) => filters[k] === o[k])
);
console.log(result);
This should do the trick!
const exampleData = [
{
"level": "1",
"objectId": "11",
"objectIdNo": "320",
"wpId": "123",
},
{
"level": "2",
"objectId": "12",
"objectIdNo": "321",
"wpId": "123",
},
{
"level": "2",
"objectId": "13",
"objectIdNo": "322",
"wpId": "120",
},
];
const filterObject1 = {
"level": "2",
}
const filterObject2 = {
"level": "2",
"wpId": "123"
}
function filter(data, filterObject) {
const filterValues = Object.entries(filterObject)
let filteredData = data
for(const [filterKey, filterValue] of filterValues) {
filteredData = filteredData.filter(obj => obj[filterKey] === filterValue)
}
return filteredData
}
console.log(filter(exampleData, filterObject1))
console.log(filter(exampleData, filterObject2))
You can do like this:
const data = [
{
level: "1",
objectId: "11",
objectIdNo: "320",
wpId: "123",
},
{
level: "2",
objectId: "12",
objectIdNo: "321",
wpId: "123",
},
{
level: "2",
objectId: "13",
objectIdNo: "322",
wpId: "120",
},
];
const filterObject = {
level: "2",
wpId: "123",
};
const result = data.filter((item) => {
let flag = true;
Object.keys(filterObject).forEach((key) => {
if (item[key] !== filterObject[key]) {
flag = false;
return;
}
});
return flag;
});
console.log(result);
const input = [ { "level": "1", "objectId": "11", "objectIdNo": "320", "wpId": "123" }, { "level": "2", "objectId": "12", "objectIdNo": "321", "wpId": "123", }, { "level": "2", "objectId": "13", "objectIdNo": "322", "wpId": "120" }, ]
const filter = { "level": "2", "wpId": "123" };
const filteredOutput = input.filter( obj => {
return Object.keys(filter).every( filterKeys => {
return obj[filterKeys] === filter[filterKeys]
});
});
console.log(filteredOutput);

Nested JSON - Join sub-object

How can I remove sub-objects?
[{
"id": "1",
"desc": "SOME PRODUCT",
"codigo": "CODE-28",
"codigoBarras": "2000000001",
"unidade": "PCT",
"price": "24.15",
"current_inventory": [{
"2kg": "5",
"5kg": "5",
"10kg": "5",
"20kg": "5",
"productId": "1"
}]
}]
[{
"id": "1",
"desc": "SOME PRODUCT",
"codigo": "CODE-28",
"codigoBarras": "2000000001",
"unidade": "PCT",
"price": "24.15",
"current_inventory_2kg": "5",
"current_inventory_5kg": "5",
"current_inventory_10kg": "5",
"current_inventory_20kg": "5",
}]
Use Object.keys() and a forEach loop
var x =[
{
"id": "1",
"desc": "SOME PRODUCT",
"codigo": "CODE-28",
"codigoBarras": "2000000001",
"unidade": "PCT",
"price": "24.15",
"current_inventory": [
{
"2kg": "5",
"5kg": "5",
"10kg": "5",
"20kg": "5",
"productId": "1"
}
]
}
]
x[0].current_inventory.forEach(e=>{
Object.keys(e).forEach(j=>{
x[0]['current_inventory_'+j]=e[j];
})
delete x[0].current_inventory
})
console.log(x)
Use Object.entries and reduce will simplify.
const data = [
{
id: "1",
desc: "SOME PRODUCT",
codigo: "CODE-28",
codigoBarras: "2000000001",
unidade: "PCT",
price: "24.15",
current_inventory: [
{
"2kg": 5,
"5kg": 5,
"10kg": 5,
"20kg": 5,
productId: 1
}
]
}
];
const [first] = data;
const updated = Object.entries(first).reduce((acc, [key, value]) => {
if (Array.isArray(value)) {
value.forEach(item =>
Object.entries(item).forEach(
([cKey, cValue]) => (acc[`${key}_${cKey}`] = cValue)
)
);
} else {
acc[key] = value;
}
return acc;
}, {});
console.log(updated);
THANK YOU VERY MUCH!!!
Solved using the code below:
data is de object
estoqueFracionado is the sub-object
for (let [key, value] of Object.entries(data)) {
value.estoqueFracionado.forEach (e => {
Object.keys(e).forEach(j => {
value['estoqueFracionado_' + j] = e[j]
})
delete value.estoqueFracionado
})
}

Converting given structure two-dimensional array into array of nested objects

I have a sorted two-dimensional array as an input. I need to get an array of nested objects in the same structure as shown below. How do I get an expected output?
input = [
["1", "2", "3", "4", "5", "6", "7", "8"],
["1", "2", "3", "4", "5", "6", "7", "9"],
["cat", "accessories", "clothes"],
["cat", "food", "dry"],
["cat", "food", "wet"],
["dog", "drinks"],
["dog", "food"]];
This is what i tried:
var output = [];
input.forEach((v, i) => {
if (i !== 0){
var temp_obj = {};
for(let j=0; j<v.length; j++){
if (input[i-1][j] === v[j]){
temp_obj[input[i-1][j]] = [];
}else if (!_.isEmpty(temp_obj) && typeof(input[i-1][j]) !== 'undefined'){
console.log('this is it ', temp_obj)
}
}
if (!_.isEmpty(temp_obj)){
output.push(temp_obj);
}
}
})
console.log(output)
expected output
output = [{
"1": [{
"2": [{
"3": [{
"4": [{
"5": [{
"6": [{
"7": [{
"8": []
}, {
"9": []
}]
}]
}]
}]
}]
}]
}]
},
{
"cat": [{
"accessories": [{
"clothes": []
}]
}, {
"food": [{
"dry": []
}, {
"wet": []
}]
}]
},
{
"dog": [{
"food": []
}, {
"drinks": []
}]
}
]
Reduce is your friend
input = [
["1", "2", "3", "4", "5", "6", "7", "8"],
["1", "2", "3", "4", "5", "6", "7", "9"],
["cat", "accessories", "clothes"],
["cat", "food", "dry"],
["cat", "food", "wet"],
["dog", "drinks"],
["dog", "food"]
];
const structure = input.reduce((obj, arr) => {
const last = arr.pop()
const chain = arr.reduce((o, key) => {
o[key] = o[key] || {}
return o[key]
}, obj)
chain[last] = []
return obj
}, {})
//console.log(structure)
var finalArray = Object.entries(structure).map(
([k,v]) => ({[k]:v})
)
console.log(finalArray)
You could find the wanted object with the key for each nested level.
var input = [["1", "2", "3", "4", "5", "6", "7", "8"], ["1", "2", "3", "4", "5", "6", "7", "9"], ["cat", "accessories", "clothes"], ["cat", "food", "dry"], ["cat", "food", "wet"], ["dog", "drinks"], ["dog", "food"]],
result = input.reduce((r, keys) => {
keys.reduce((a, k) => {
var temp = a.find(o => k in o);
if (!temp) a.push(temp = { [k]: [] });
return temp[k];
}, r);
return r;
}, []);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Compare Object properties that contain array with each other to find difference

Problem:
I am working on a mini project involving a JSON file and express/nodejs and I am stuck on a portion that contains the following instructions:
Using a post route, determine the user's most compatible friend using
the following rules: Convert each user's results into a simple array
of numbers.
Compare the difference between current user's scores against those
from potential matches, question by question. Add up the differences
to calculate the totalDifference.
Example: User 1: [5, 1, 4, 4, 5, 1, 2, 5, 4, 1] User 2: [3, 2, 6, 4,
5, 1, 2, 2, 4, 1]
Total Difference: 2 + 1 + 2 + 3 = 8
Remember to use the absolute value of the differences; no negative
results! Your app should calculate both 5-3 and 3-5 as 2, etc.
I am able to get the results that look like this (the submitted array is the last array all 5's):
Here is the portion of code I am using for that:
app.post('/surveyResponse', function(req,res){
let photo = req.body.url;
let name = req.body.name;
let travel = req.body.travel;
let affection = req.body.affection;
let family = req.body.family;
let fitness = req.body.fitness;
let movie = req.body.movie;
let education = req.body.education;
let career = req.body.career;
let marriage = req.body.marriage;
let children = req.body.children;
let pets = req.body.pets;
let sum = 0;
let obj = {};
let person = {
name: name,
photo: photo,
scores: [
travel,
affection,
family,
fitness,
movie,
education,
career,
marriage,
children,
pets
]
}
//finding the sum of all the numbers
for(i in person.scores){
sum+=Number(person.scores[i]);
}
//form submission results
let score = person.scores;
// Read the file and send to the callback
fs.readFile('./app/data/friends.json', handleFile)
// Write the callback function
function handleFile(err, data) {
if (err) throw err
obj = JSON.parse(data)
for(var key in obj){
var obj2 = obj[key];
console.log(obj2.scores);
}
//this is the console.log for my form submission array
console.log(score);
}
//------------------------------------
// result that prints out on the HTML
res.send('Your name is ' + name + ' You Score is ' + sum );
});
GOAL
The goal is the find the user with the least difference between their results and what the user submitted.
RESEARCH
I have done research How to compare each object in an array with each other. When found update the object with a new property How to Subtract Multiple Objects from an Array with Another array
and most of the examples deal with having separate JSON objects and comparing them to each other and the one I found that compared an array of JSON objects was just comparing phone numbers. I am stuck on my next steps. I just need a jump start/guidance please.
Here is the JSON file I am working with:
[
{
"name": "Mike Jackson",
"photo": "./app/public/matchPhotos/photo0.jpg",
"scores": [
"3",
"2",
"4",
"3",
"3",
"4",
"4",
"4",
"3",
"4"
]
},
{
"name": "Jermaine Subia",
"photo": "./app/public/matchPhotos/photo1.jpg",
"scores": [
"4",
"4",
"2",
"2",
"4",
"5",
"3",
"4",
"5",
"2"
]
},
{
"name": "Taji Gibson",
"photo": "./app/public/matchPhotos/photo2.jpg",
"scores": [
"1",
"5",
"3",
"2",
"3",
"1",
"3",
"4",
"3",
"3"
]
},
{
"name": "Jamie Schully",
"photo": "./app/public/matchPhotos/photo3.jpg",
"scores": [
"5",
"3",
"3",
"4",
"2",
"4",
"4",
"5",
"5",
"5"
]
},
{
"name": "Justin Andres",
"photo": "./app/public/matchPhotos/photo4.jpg",
"scores": [
"2",
"1",
"1",
"1",
"2",
"3",
"2",
"2",
"2",
"4"
]
},
{
"name": "Austin Brooks",
"photo": "./app/public/matchPhotos/photo5.jpg",
"scores": [
"2",
"3",
"4",
"2",
"4",
"4",
"4",
"4",
"5",
"4"
]
},
{
"name": "Jessica Jones",
"photo": "./app/public/matchPhotos/photo6.jpg",
"scores": [
"4",
"4",
"4",
"4",
"4",
"4",
"4",
"4",
"5",
"4"
]
},
{
"name": "Jasmine Love",
"photo": "./app/public/matchPhotos/photo7.jpg",
"scores": [
"4",
"3",
"3",
"2",
"2",
"2",
"2",
"1",
"2",
"1"
]
},
{
"name": "Sandra Smith",
"photo": "./app/public/matchPhotos/photo8.jpg",
"scores": [
"1",
"2",
"2",
"2",
"4",
"3",
"4",
"3",
"3",
"1"
]
},
{
"name": "Kevin Hart",
"photo": "./app/public/matchPhotos/photo9.jpg",
"scores": [
"5",
"5",
"3",
"3",
"2",
"2",
"5",
"5",
"4",
"3"
]
}
]
UPDATE 1
I am trying to incorporate the following code but am not understanding as to why I keep getting the following error:
ReferenceError: data is not defined
I believe it has to do with how I am trying to incorporate the incoming data. I took the code and tried to translate it to fit my code.
// Read the file and send to the callback
fs.readFileSync('./app/data/friends.json', findCompatibility); <---- This is the line I think is causing issues
// Write the callback function
function findCompatibility(data) {
var results = [];
for (let i = 0; i < data.length; i++) {
for (let j = 1; j < data.length - 1; j++) {
const user1 = data[i];
const user2 = data[j];
var difference = 0;
for (let k = 0; k < user1.scores.length; k++) {
difference += Math.abs(Number(user1.scores[k]) - Number(user2.scores[k]));
}
results.push({"name": user1.name, "friend": user2.name, "difference": difference});
}
}
return results;
}
console.log(findCompatibility(data));
Some pointers to point you in right direction:
To ensure that differences aren't negative use Math.abs() to get the absolute value of the difference.
Right now all the scores are strings, convert them to number using Number() or parseInt().
var data = [ { "name": "Mike Jackson", "photo": "./app/public/matchPhotos/photo0.jpg", "scores": [ "3", "2", "4", "3", "3", "4", "4", "4", "3", "4" ] }, { "name": "Jermaine Subia", "photo": "./app/public/matchPhotos/photo1.jpg", "scores": [ "4", "4", "2", "2", "4", "5", "3", "4", "5", "2" ] }, { "name": "Taji Gibson", "photo": "./app/public/matchPhotos/photo2.jpg", "scores": [ "1", "5", "3", "2", "3", "1", "3", "4", "3", "3" ] }, { "name": "Jamie Schully", "photo": "./app/public/matchPhotos/photo3.jpg", "scores": [ "5", "3", "3", "4", "2", "4", "4", "5", "5", "5" ] }, { "name": "Justin Andres", "photo": "./app/public/matchPhotos/photo4.jpg", "scores": [ "2", "1", "1", "1", "2", "3", "2", "2", "2", "4" ] }, { "name": "Austin Brooks", "photo": "./app/public/matchPhotos/photo5.jpg", "scores": [ "2", "3", "4", "2", "4", "4", "4", "4", "5", "4" ] }, { "name": "Jessica Jones", "photo": "./app/public/matchPhotos/photo6.jpg", "scores": [ "4", "4", "4", "4", "4", "4", "4", "4", "5", "4" ] }, { "name": "Jasmine Love", "photo": "./app/public/matchPhotos/photo7.jpg", "scores": [ "4", "3", "3", "2", "2", "2", "2", "1", "2", "1" ] }, { "name": "Sandra Smith", "photo": "./app/public/matchPhotos/photo8.jpg", "scores": [ "1", "2", "2", "2", "4", "3", "4", "3", "3", "1" ] }, { "name": "Kevin Hart", "photo": "./app/public/matchPhotos/photo9.jpg", "scores": [ "5", "5", "3", "3", "2", "2", "5", "5", "4", "3" ] } ];
function findCompatibility(data) {
var results = [];
for (let i = 0; i < data.length; i++) {
for (let j = 1; j < data.length - 1; j++) {
const user1 = data[i];
const user2 = data[j];
var difference = 0;
for (let k = 0; k < user1.scores.length; k++) {
difference += Math.abs(Number(user1.scores[k]) - Number(user2.scores[k]));
}
results.push({"name": user1.name, "friend": user2.name, "difference": difference});
}
}
return results;
}
console.log(findCompatibility(data));
var arr1 = [1,4,7,88,40];
var arr2 = [1,77,3,45];
function diff(a1, a2){
var s1 = a1.reduce((red,n) => red+n);
var s2 = a2.reduce((red,n) => red+n);
var total = s1 - s2;
return total >= 0 ? total : -1*total;
}
console.log(diff(arr2, arr1));

JS json array compare array and remove duplicates

I have below two arrays which are similar in structure except for additional key in the array 1 When I get array 2 I would like to remove duplicates from array 2 if they are already present in array 1.
For e.g. 2nd item is a duplicate.
Array 1:
[{
"from": "1",
"to": "2",
"text": "test",
"_goid": "1234"
}, {
"from": "3",
"to": "4",
"text": "test",
"_goid": "12345"
}, {
"from": "5",
"to": "6",
"text": "test",
"_goid": "123456"
}]
Array 2: (only difference is it does not contain key _goid)
[{
"from": "4",
"to": "8",
"text": "test"
},{
"from": "3",
"to": "4",
"text": "test"
},{
"from": "9",
"to": "10",
"text": "test"
}]
I have below code which removes duplicates if arrays are exactly same but not working for my case.
function removeDuplicatesJson(myArr) {
var props = Object.keys(myArr[0])
return myArr.filter((item, index, self) =>
index === self.findIndex((t) => (
props.every(prop => {
return t[prop] === item[prop]
})
))
)
}
The below code will do as you ask: remove any items from arr2 which already present in arr1:
var arr1 = [{
"from": "1",
"to": "2",
"text": "test",
"_goid": "1234"
}, {
"from": "3",
"to": "4",
"text": "test",
"_goid": "12345"
}, {
"from": "5",
"to": "6",
"text": "test",
"_goid": "123456"
}]
var arr2 = [{
"from": "4",
"to": "8",
"text": "test"
},{
"from": "3",
"to": "4",
"text": "test"
},{
"from": "9",
"to": "10",
"text": "test"
}]
// create a flat array of values to test against:
var arr1_keys = arr1.map(item => item.from + item.to);
// ["12", "34", "56"]
// filter out the dups and create a dup-free array
arr2 = arr2.filter(item => !arr1_keys.includes(item.from + item.to))
console.log(arr2)
I'm not sure if it's what you want but it might help you.
1.
Faster but limited option (depends on the amount of data), only if you're sure about objects signature, the order of properties is important:
const removeDuplicates = (baseArray, toDedupe) => {
const baseArrayFormatted = baseArray.map(({ _goid, ...restProps }) => JSON.stringify(restProps));
return toDedupe
.map(item => JSON.stringify(item))
.filter((item) => !baseArrayFormatted.some(baseItem => baseItem === item))
.map(item => JSON.parse(item));
}
2.
Slower but more accurate:
const removeDuplicates = (baseArray, toDedupe) => {
const props = Object.keys(toDedupe[0]);
return toDedupe
.filter((item) => !baseArray.some(baseItem => props.every(prop => baseItem[prop] === item[prop])))
}
Keep in mind that there is no checking of objects signature, also there is a lof of validation missing (if it's really an objects, if it's a function etc, but I believe it's not the question here).

Categories

Resources