Get array of same object from two arrays - javascript

the first one is a global list of products (say 10 products) that each product contains a code and a quantity greater than or equal to 0. (this is important)
the second is a list of products (say 3) that each product contains a code (the same as in the first table) and a quantity equal to 0.
I want to filter the first array and have an array with 3 product but keep the quantities of the first one
for example:
state.Data = [
{
"code": "0",
"qte": "0"
},
{
"code": "1",
"qte": "0"
},
{
"code": "2",
"qte": "14"
},
{
"code": "3",
"qte": "14"
},
{
"code": "4",
"qte": "0"
},
{
"code": "5",
"qte": "0"
},
{
"code": "6",
"qte": "0"
},
{
"code": "7",
"qte": "0"
},
{
"code": "8",
"qte": "0"
},
{
"code": "9",
"qte": "0"
}
];
action.value.Data = [
{
"code": "0",
"qte": "0"
},
{
"code": "2",
"qte": "0"
},
{
"code": "3",
"qte": "0"
}
];
// what I want:
result = [
{
"code": "0",
"qte": "0"
},
{
"code": "2",
"qte": "14"
},
{
"code": "3",
"qte": "14"
}
];
the difference between action.value.Data and result is qte of each product.
I had tried:
const mainData = [...action.value.Data,...state.Data];
var catData = mainData.reduce((p, c) => {
p[c.code] = (p[c.code] || 0) ;
return p;
}, {});
var result = mainData.filter((obj) => {
return catData[obj.code] >= 0;
});
nextState = {
...state,
Data: result,
}
but the result table gives me 6 products instead of 3 (always double) and the qte is always 0, so how to filter the state.Data array and keep only the products which have the same code as in the action.value.Data array

I can not understand the logic of your code actually. Solution is extremely simple
// step 1: getting keys
const keys = action.value.Data.map(v => v.code)
// step 2: filter values with these keys
const values = state.Data.filter(v => keys.includes(v.code))
That's it

This can be easily done with one liner. All you want to do is filter the first array checking which items are on the second array:
const result = state.Data.filter(({code}) =>
action.value.Data.some(x => x.code === code))
console.log(result)
You get exactly the value you want.

const state = {Data:[
{"code": "0","qte": "0"},{"code": "1","qte": "0"},{"code": "2","qte": "14"},{"code": "3","qte": "14"},
{"code": "4","qte": "0"},{"code": "5","qte": "0"},{"code": "6","qte": "0"},{"code": "7","qte": "0"},
{"code": "8","qte": "0"},{"code": "9","qte": "0"}
]},
action = {value:{Data:[
{"code": "0","qte": "0"},{"code": "2","qte": "0"},{"code": "3","qte": "0"}
]}};
const res = state.Data.filter(o=>action.value.Data.some(a=>a.code==o.code));
console.log(res)

You can just filter the global products based on the codes in action.value.Data but you can also try the below solution to avoid nested loops.
Create a map with code as keys, qte as values and use it while mapping the action.value.Data.
const global = [{
"code": "0",
"qte": "0"
},
{
"code": "1",
"qte": "0"
},
{
"code": "2",
"qte": "14"
},
{
"code": "3",
"qte": "14"
},
{
"code": "4",
"qte": "0"
},
{
"code": "5",
"qte": "0"
},
{
"code": "6",
"qte": "0"
},
{
"code": "7",
"qte": "0"
},
{
"code": "8",
"qte": "0"
},
{
"code": "9",
"qte": "0"
}
];
const bla = [{
"code": "0",
"qte": "0"
},
{
"code": "2",
"qte": "0"
},
{
"code": "3",
"qte": "0"
}
];
const codeVsQty = new Map(global.map(({code, qte}) => [code, qte]));
const result = bla.map(({code}) => ({code, qte: codeVsQty.get(code)}));
console.log(result)

Related

How to filter from an array of objects one value and reduce it to one result per value without duplicates [duplicate]

This question already has answers here:
Get all unique values in a JavaScript array (remove duplicates)
(91 answers)
Remove duplicates form an array
(17 answers)
Closed 1 year ago.
I'm trying to build a method in javascript which can filter from an array of object one only value and have a result that value only once without having duplicates
sharing a snippet and more details what I want to achieve
const arr = [{
"id": "1",
"value": "something"
}, {
"id": "1",
"value": "something"
}, {
"id": "2",
"value": "something"
}, {
"id": "2",
"value": "something"
},
{
"id": "3",
"value": "something"
},
{
"id": "3",
"value": "something"
},
{
"id": "3",
"value": "something"
}];
const result = arr.filter(res => res.id).map(ele => ele.id);
console.log(result);
As you see result is an array like this
["1", "1", "2", "2", "3", "3", "3"]
What I would like to get is as follow
["1", "2", "3"]
The idea is to extract only one ID per result.
You can use a Set as follows:
const arr = [
{ "id": "1", "value": "something" },
{ "id": "1", "value": "something" },
{ "id": "2", "value": "something" },
{ "id": "2", "value": "something" },
{ "id": "3", "value": "something" },
{ "id": "3", "value": "something" },
{ "id": "3", "value": "something" }
];
const result = [...arr.reduce((set,{id}) => {
set.add(id);
return set;
}, new Set)];
console.log(result);

sorting json tree with multiple property

i have prepared a json tree from a plain json. But i need to sort the tree with multiple conditions.
for example at level 1 we have multiple objects. we need to sort with level and then with a name property.
level is a number and name is an alphanumeric. so name sorting is alphabets first and then numbers
Below is the input json
var inputJson = [
{
"level": "1",
"leafFlag": "1",
"path":"p123",
"name":"food23"
},
{
"level": "1",
"leafFlag": "1",
"path":"r125",
"name":"car1"
},
{
"level": "2",
"leafFlag": "0",
"path":"p123/p345",
"name":"apple345"
},
{
"level": "2",
"leafFlag": "1",
"path":"p123/p095",
"name":"123banana"
},
{
"level": "3",
"leafFlag": "0",
"path":"p123/p095/p546",
"name":"543"
},
{
"level": "2",
"leafFlag": "1",
"path":"r125/yhes",
"name":"tata78"
}
]
var output = [];
The below code prepares the json tree.
I tried here for sorting with multiple properties
inputJson = inputJson.sort((a, b) => (parseInt(a.level) > parseInt(b.level)) ? 1 : -1)
inputJson.forEach(v => {
if (v.level == "1") {
v.children = [];
output.push(v);
}
else {
pathValues = v.path.split("/");
pathValues.pop();
var node = null;
var fullPath = "";
pathValues.forEach(p => {
fullPath = fullPath === "" ? p : fullPath + "/" + p;
node = (node == null ? output : node.children).find(o => o.path === fullPath);
})
node.children = node.children || [];
node.children.push(v);
}
})
Output from above:
var output = [
{
"level": "1",
"leafFlag": "1",
"path": "p123",
"name": "food23",
"children": [
{
"level": "2",
"leafFlag": "0",
"path": "p123/p345",
"name": "apple"
},
{
"level": "2",
"leafFlag": "1",
"path": "p123/p095",
"name": "banana",
"children": [
{
"level": "3",
"leafFlag": "0",
"path": "p123/p095/p546",
"name": "grapes"
}
]
}
]
},
{
"level": "1",
"leafFlag": "1",
"path": "r125",
"name": "car",
"children": [
{
"level": "2",
"leafFlag": "1",
"path": "r125/yhes",
"name": "tata",
"children": [
{
"level": "3",
"leafFlag": "0",
"path": "r125/yhes/sdie",
"name": "Range Rover"
}
]
},
{
"level": "2",
"leafFlag": "0",
"path": "r125/theys",
"name": "suzuki"
}
]
}
]
Expected output:
[
{
"level": "1",
"leafFlag": "1",
"path": "r125",
"name": "car",
"children": [
{
"level": "2",
"leafFlag": "0",
"path": "r125/theys",
"name": "suzuki"
},
{
"level": "2",
"leafFlag": "1",
"path": "r125/yhes",
"name": "tata",
"children": [
{
"level": "3",
"leafFlag": "0",
"path": "r125/yhes/sdie",
"name": "Range Rover"
}
]
}
]
},
{
"level": "1",
"leafFlag": "1",
"path": "p123",
"name": "food",
"children": [
{
"level": "2",
"leafFlag": "0",
"path": "p123/p345",
"name": "apple"
},
{
"level": "2",
"leafFlag": "1",
"path": "p123/p095",
"name": "banana",
"children": [
{
"level": "3",
"leafFlag": "0",
"path": "p123/p095/p546",
"name": "grapes"
}
]
}
]
}
]
I tried something like below
inputJson = inputJson.sort((a, b) => (parseInt(a.level) > parseInt(b.level)) ? 1 : -1 && a.name > b.name ? 1 ? -1)
You could take a single sort by sorting levels first and then by name.
.sort((a, b) => a.level - b.level || a.name.localeCompare(b.name))
Then build the tree with the sorted items.
var data = [{ level: "1", leafFlag: "1", path: "p123", name: "food" }, { level: "1", leafFlag: "1", path: "r125", name: "car" }, { level: "2", leafFlag: "0", path: "p123/p345", name: "apple" }, { level: "2", leafFlag: "1", path: "p123/p095", name: "banana" }, { level: "3", leafFlag: "0", path: "p123/p095/p546", name: "grapes" }, { level: "2", leafFlag: "1", path: "r125/yhes", name: "tata" }],
result = data
.sort((a, b) => a.level - b.level || a.name.localeCompare(b.name))
.reduce((r, o) => {
let p = o.path.split('/');
p.pop();
let target = p.reduce((t, _, i, p) => {
var path = p.slice(0, i + 1).join('/'),
temp = (t.children = t.children || []).find(q => q.path === path);
if (!temp) t.children.push(temp = { path }); // this is not necessary
// if all nodes are given
return temp;
}, { children: r });
(target.children = target.children || []).push({ ...o });
return r;
}, []);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
var rootes= inputJson.filter(x=>x.level=='1')
for(i=0;i<rootes.length;i++){
rootes[i].children=[] }
var objwithchild = inputJson.filter(x=>x.leafFlag=='1')
for(i=0;i<objwithchild.length;i++){
objwithchild[i].children=[] }
inputJson.forEach(x=>{
patharr=x.path.split('/')
path=patharr.pop()
switch (x.level) {
case '2':
rootes.filter(p=>{if(p.path==patharr[0]){p.children.push(x)}
})
break
case '3':
objwithchild.filter(p=>{if(p.path==patharr[0]+'/'+patharr[1]){p.children.push(x)}
})
break
}
})
console.dir(rootes,{depth:null})
You should first sort by name, then re-sort the sorted array by level.
inputJson = inputJson.sort((a,b) => {return a.name > b.name}).sort((a,b) => {return (Number(a.level) - Number(b.level)};

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).

Access JSON data returned from CMS

The CMS I am using will give me JSON data of each item within a database. I use the following code to access this data:
var items = new BCAPI.Models.WebApp.ItemCollection("Strain Bank");
items.fetch({
success: function (items) {
items.each(function (item) {
item.fetch({
success: function (itemDetails) {
console.log(JSON.stringify(itemDetails.attributes))
}
});
});
}
});
This console.log(JSON.stringify(itemDetails.attributes)) outputs the following code for each item. An example of an items code is below:
{
"id": 4441485,
"name": "Alien OG",
"fields": {
"Buzz Length": "580",
"Strength": "37",
"Sativa Percentage": "231",
"Overall Rating": "40",
"Flower Time": "61",
"Potency": "10",
"Yield": "10",
"Height": "20",
"Reviews": "4",
"Grow Reviews": "1",
"Creative": "2",
"Euphoric": "0",
"Uplifted": "0",
"Energetic": "2",
"Lazy": "0",
"Focused": "2",
"Happy": "1",
"Talkative": "0",
"Giggly": "0",
"Tingly": "0",
"Hungry": "0",
"Sleepy": "0",
"Aroused": "0",
"Migraines": "1",
"Nausea": "0",
"Insomnia": "0",
"Pain": "2",
"Anxiety": "0",
"Stress": "2",
"PMS": "0",
"Lack of Appetite": "0",
"Muscle Spasms": "0",
"Depression": "2",
"Seizures": "0",
"Fatigue": "1",
"Fruity": "0",
"Citrus": "0",
"Seasonings-Spicy": "1",
"Floral": "2",
"Pungent": "2",
"Chemical": "1",
"Earthy": "2",
"Sweet": "0",
"Grass": "1",
"Skunky": "0"
}
}
What I need to do is access the data within each item. I am unsure how to do this. I tried:
//Thecode below replaces console.log(JSON.stringify(itemDetails.attributes)) in the above example.
var json = JSON.stringify(itemDetails.attributes)
$.each($.parseJSON(json), function(idx, obj) {
console.log(obj.name);
});
When I try the above code I see two things in the console.log:
TypeError: obj is null
and
undefined
How do I properly access the JSON data?
You should be able to access data in each item by . notation, like itemDetails.attributes.id, itemDetails.attributes.name and itemDetails.attributes.fields
Replace below:
console.log(JSON.stringify(itemDetails.attributes))
With below and try
console.log(itemDetails.attributes.name);
You are accessing the desired object wrongly. Try,
$.each(xObj.fields, function (key, val) {
console.log(key + " : " + val);
});
DEMO

Categories

Resources