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));
Related
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)
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; }
My console shows me the total of all the scores but I would like it to print 32 and 35 instead of 65. The end result is I want to push each total into an array.
var peopleArray = [
{
name: "Hector Valdes",
photo: "",
scores: [
"5", "1",
"4", "4",
"5", "1",
"2", "5",
"4", "1"
]
}, {
name: "Tyler Williams",
photo: "",
scores: [
"5", "1",
"4", "4",
"5", "2",
"2", "5",
"4", "1"
]
}
]
let total = 0;
for (i = 0; i < peopleArray.length; i++){
for(j=0; j < peopleArray[i].scores.length; j++){
total += Number(peopleArray[i].scores[j]);
console.log(total);
};
};
You can use map to loop thru each peopleArray element. Use reduce to sum the scores.
One option in converting a string to number by adding + before the string.
var peopleArray = [{"name":"Hector Valdes","photo":"","scores":["5","1","4","4","5","1","2","5","4","1"]},{"name":"Tyler Williams","photo":"","scores":["5","1","4","4","5","2","2","5","4","1"]}];
var total = peopleArray.map(o => o.scores.reduce((c, v) => +c + +v));
console.log(total);
var peopleArray = [
{
name: "Hector Valdes",
photo: "",
scores: [
"5", "1",
"4", "4",
"5", "1",
"2", "5",
"4", "1"
]
}, {
name: "Tyler Williams",
photo: "",
scores: [
"5", "1",
"4", "4",
"5", "2",
"2", "5",
"4", "1"
]
}
]
let total = peopleArray.map(i => {
return i.scores.reduce((a, b) => parseInt(a) + parseInt(b), 0)
})
console.log(total)
Try this,
you need to move total in the first loop then just need to add a new total object in array
var peopleArray = [
{
name: "Hector Valdes",
photo: "",
scores: [
"5", "1",
"4", "4",
"5", "1",
"2", "5",
"4", "1"
]
}, {
name: "Tyler Williams",
photo: "",
scores: [
"5", "1",
"4", "4",
"5", "2",
"2", "5",
"4", "1"
]
}
];
console.log(peopleArray);
for (i = 0; i < peopleArray.length; i++){
let total = 0;
for(j=0; j < peopleArray[i].scores.length; j++){
total += Number(peopleArray[i].scores[j]);
};
peopleArray[i]['total'] = total;
console.log(total);
};
console.log(peopleArray);
Try this
const result = peopleArray.map((value) => {
return {
name: value.name,
score: value.scores.reduce((total, score) => total + Number(score), 0)
}
})
console.log(result);
Try this, Hope it helps..
let scoresArr = peopleArray.map(data => {
return data.scores.reduce((a,b) => parseFloat(a) + parseFloat(b), 0)
})
console.log(scoresArr)
How can I append a text to only the first value of an array and send the array back to the server. This is the response i am getting from the server
[{
"12": [ "12", "1", "2", "3" ]
}, {
"13": [ "13", "1", "2", "3" ]
}, {
"14": [ "14", "1", "2", "3" ]
}, {
"15": [ "15", "1", "2", "3" ]
}]
I want my array to now be like this so that i can pass this array to my data table.
var object = [{
12: ["12 hrs", "1", "2", "3"]
}, {
13: ["13 hrs", "1", "2", "3"]
}, {
14: ["14 hrs", "1", "2", "3"]
}, {
15: ["15 hrs", "1", "2", "3"]
}]
How can I append hrs to the first value?
Here's one easy method...
// Parse the string response from the server into an object
var obj = JSON.parse(serverResponse);
// loop through the object, knowing that it's nested in the first index of an array "obj[0]"
for(id in obj[0]){
// obj->arrayIndex->objectProperty->arrayIndex append " hrs"
obj[0][id][0] += " hrs";
}
// to return this to the server, apply JSON.stringify(obj)
I fixed object in your question to -
var objectArray = [{"12" : ["12", "1", "2", "3"]}, {"13" : ["13", "1", "2", "3"]},{"14" : ["14", "1", "2", "3"]},{"15" : ["15", "1", "2", "3"]}]
This is how you can loop through the objectArray and change in the way you wanted -
for(var i=0;i<objectArray.length;i++)
{
for(var key in objectArray[i])
{
objectArray[i][key][0]+=" hrs";
break;
}
}
console.log(objectArray)
Is it possible to make access to a property of an object into an array of objects like a matrix?
I mean something like this:
jSon generated object:
[
{
"Nome": "1",
"Departamento": "1",
"Cargo": "1"
},
{
"Nome": "5",
"Departamento": "5",
"Cargo": "5"
},
{
"Nome": "2",
"Departamento": "2",
"Cargo": "2"
},
{
"Nome": "3",
"Departamento": "33",
"Cargo": "33"
},
{
"Nome": "4",
"Departamento": "4",
"Cargo": "4"
}
]
How I'm trying access the object properties:
object[0][1] = value;
What I already do:
object[0]["Nome"] = value;
I've searched a lot, but I can't find a solution for this problem.
No.
Objects and Arrays are two very different types in JavaScript. In an Array order is very important but order is not retained for Object keys. Keep in mind you can still iterate over the keys of an Object.
for (var prop in myObj) {
console.log("myObj.prop -> ", myObj[prop]);
}
As already stated, Arrays and Objects are different. I don't really follow your reasoning for converting from one structure to the other, and you should probably consider working in a different way, which is totally possible from your question and comment descriptions. But, if you really must convert then you will need to perform some kind of mapping, to and from, to be sure that things are ordered correctly. You could do something like this.
Javascript
function toMapped (array) {
var mapping = {
"Nome": 0,
"Departamento": 1,
"Cargo": 2
},
mapped = [],
length = array.length,
i = 0,
element,
j;
while (i < length ) {
element = [];
for (j in mapping) {
if (mapping.hasOwnProperty(j) && array[i].hasOwnProperty(j)) {
element[mapping[j]] = array[i][j];
}
}
mapped.push(element);
i += 1;
}
return mapped;
}
function fromMapped (array) {
var mapping = {
0: "Nome",
1: "Departamento",
2: "Cargo"
},
mapped = [],
length = array.length,
i = 0,
object,
j;
while (i < length ) {
object = {};
for (j in mapping) {
if (mapping.hasOwnProperty(j) && array[i].hasOwnProperty(j)) {
object[mapping[j]] = array[i][j];
}
}
mapped.push(object);
i += 1;
}
return mapped;
}
var test = [{
"Nome": "1",
"Departamento": "1",
"Cargo": "1"
}, {
"Nome": "5",
"Departamento": "5",
"Cargo": "5"
}, {
"Nome": "2",
"Departamento": "2",
"Cargo": "2"
}, {
"Nome": "3",
"Departamento": "33",
"Cargo": "33"
}, {
"Nome": "4",
"Departamento": "4",
"Cargo": "4"
}];
var mapped = toMapped(test);
var unmapped = fromMapped(mapped);
console.log(test);
console.log(mapped);
console.log(unmapped);
On jsfiddle
Using ECMA5 Array.prototype.map
Javascript
function toMapped(array) {
var mapping = {
"Nome": 0,
"Departamento": 1,
"Cargo": 2
};
return array.map(function (object) {
var element = [],
i;
for (i in mapping) {
if (mapping.hasOwnProperty(i) && object.hasOwnProperty(i)) {
element[mapping[i]] = object[i];
}
}
return element;
});
}
function fromMapped(array) {
var mapping = {
0: "Nome",
1: "Departamento",
2: "Cargo"
};
return array.map(function (element) {
var object = {},
i;
for (i in mapping) {
if (mapping.hasOwnProperty(i) && element.hasOwnProperty(i)) {
object[mapping[i]] = element[i];
}
}
return object;
});
}
var test = [{
"Nome": "1",
"Departamento": "1",
"Cargo": "1"
}, {
"Nome": "5",
"Departamento": "5",
"Cargo": "5"
}, {
"Nome": "2",
"Departamento": "2",
"Cargo": "2"
}, {
"Nome": "3",
"Departamento": "33",
"Cargo": "33"
}, {
"Nome": "4",
"Departamento": "4",
"Cargo": "4"
}];
var mapped = toMapped(test);
var unmapped = fromMapped(mapped);
console.log(test);
console.log(mapped);
console.log(unmapped);
On jsfiddle