How to get sum of array nested in object? - javascript

{service: {
categories: [
{
name: "category1",
id: 1,
questions: [
{
id: 1,
question: "example trivia question here",
value: 2
}, {
id: 2,
question: "example trivia question here",
value: 3
}]
},
{
name: "category2",
id: 2,
questions: [
{
id: 3,
question: "example trivia question here",
value: 5
}
]
},
{
name: "category3",
id: 3
}
]
}};
For each category, I'm trying to count the answered trivia question. How do I get the sum of answered questions for each category (indicated when there is a value present)? I think there's something gone wrong in my loop. I've also tried this with array prototypes. Sorry for the noob question.
$scope.questionCount = 0;
angular.forEach($scope.service, function(categories, questions) {
for (var i = 0; i < questions.length; i++) {
if (questions[i].value !== null){
triviaCount = 0
triviaCount += 1
$scope.questionCount.push(triviaCount)
}
}
});

Use map() method provided by Array
var service = {
categories: [
{
name: "category1",
id: 1,
questions: [
{
id: 1,
question: "example trivia question here",
value: 2
}, {
id: 2,
question: "example trivia question here",
value: 3
}]
},
{
name: "category2",
id: 2,
questions: [
{
id: 3,
question: "example trivia question here",
value: 5
}
]
},
{
name: "category3",
id: 3
}
]
};
var result = service.categories.map(function(cat) {
return {
'name' : cat.name,
'count' : !!cat.questions ? cat.questions.length : 0
}
});
console.log(result);
// [{ name="category1", count=2}, { name="category2", count=1}, { name="category3", count=0}]

I am not used to with angular js but this is how i will do with js. i hope this helps you.
var json = {
service: {
categories: [{
name: "category1",
id: 1,
questions: [{
id: 1,
question: "example trivia question here",
value: 2
}, {
id: 2,
question: "example trivia question here",
value: 3
}]
}, {
name: "category2",
id: 2,
questions: [{
id: 3,
question: "example trivia question here",
value: 5
}]
}, {
name: "category3",
id: 3
}]
}
};
var qCount = 0;
categories = json.service.categories;
for (var category in categories) {
var temp = categories[category];
if (temp.questions !== undefined) {
var questions = temp.questions;
for (var que in questions) {
if (questions[que].value !== undefined)
qCount++;
}
}
}
console.log(qCount); //here is your question count

something like this? (look at the console)
console output:
category1 # of quesitons: 2
category2 # of quesitons: 1
category3 # of quesitons: 0
var service = {
categories: [
{
name: "category1",
id: 1,
questions: [
{
id: 1,
question: "example trivia question here",
value: 2
}, {
id: 2,
question: "example trivia question here",
value: 3
},
{
id: 9,
question: "example trivia question here",
value: '',
}
]
},
{
name: "category2",
id: 2,
questions: [
{
id: 3,
question: "example trivia question here",
value: 5
},
{
id: 7,
question: "example trivia question here",
value: '',
}
]
},
{
name: "category3",
id: 3,
questions: [],
}
]
};
$(document).ready(function() {
for(var i = 0; i < service.categories.length; i++ ){
var questionCount = 0;
for(var j = 0; j < service.categories[i].questions.length; j++ ) {
if (service.categories[i].questions[j].value != '' && service.categories[i].questions[j].value != undefined) {
questionCount++;
}
}
console.log(service.categories[i].name, ' # of quesitons: ', questionCount);
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

Related

How to access nested key on object with array JavaScript?

I want to make hierarchy role layout. So I want to access nested JavaScript array with in a object. Needs to add 'row' and 'column' key in every object based depth and index.
API response array like this:
const dataArray = [
{
name: "master name",
child: [
{
name: "child 1a",
child: [
{ name: "child 1a2a" },
{
name: "child 1a2b",
child: [
{ name: "child 2b3a" },
{
name: "child 2b3b",
child: [
{ name: "child 3b4a" },
{ name: "child 3b4b" },
{ name: "child 3b4c" },
],
},
{ name: "child 2b3c" },
],
},
{ name: "child 1a2c" },
],
},
{
name: "child 1b",
child: [
{ name: "child 1b2a" },
{ name: "child 1b2b" },
{ name: "child 1b2c" },
],
},
],
},
];
This is what I have tried, row key added following code, need help for column
const assignDepth = (arr, row = 0, index = 0) => {
if (index < arr.length) {
arr[index].row = row;
if (arr[index].hasOwnProperty("child")) {
return assignDepth(arr[index].child, row + 1, 0);
}
return assignDepth(arr, row, index + 1);
}
return;
};
await assignDepth(dataArray);
console.log(JSON.stringify(dataArray, undefined, 4));
Then my expected result array is:
const resultArray = [
{
name: "master name",
row: 0,
column: 0,
child: [
{
name: "child 1a",
row: 1,
column: 1,
child: [
{ name: "child 1a2a", row: 2, column: 1 },
{
name: "child 1a2b",
row: 2,
column: 2,
child: [
{ name: "child 2b3a", row: 3, column: 1 },
{
name: "child 2b3b",
row: 3,
column: 2,
child: [
{ name: "child 3b4a", row: 4, column: 1 },
{ name: "child 3b4b", row: 4, column: 2 },
{ name: "child 3b4c", row: 4, column: 3 },
],
},
{ name: "child 2b3c", row: 3, column: 3 },
],
},
{ name: "child 1a2c", row: 2, column: 3 },
],
},
{
name: "child 1b",
row: 1,
column: 2,
child: [
{ name: "child 1b2a", row: 2, column: 4 },
{ name: "child 1b2b", row: 2, column: 5 },
{ name: "child 1b2c", row: 2, column: 6 },
],
},
],
},
];
So how can I render this, Anyone help me out. Thanks in advance!
You can try the following logic:
var ranking = {0:0};
let addRowColumn = (data,row=0) =>{
data.forEach(item=>{
item.row = row;
item.column = ranking[row];
ranking[row]+=1;
if(item.child && item.child.length){
ranking[row+1] = ranking[row+1] || 1;
addRowColumn(item.child,row+1);
}
});
};
addRowColumn(dataArray);
console.log(dataArray);
This is tested. you can change the ranking object to start with a specific row and column. The key of object represents the row and value represents the column of data.

Remove duplicate elements of an array, in an object of arrays, dynamically

I have checked other solutions but none fit the criterion of my problem
This solution does not have the ability to dynamically check each node
Problem summarized
I wish to create an algorithm that is able to check an object that has nodes of different data types, for duplicated objects in nodes that are specifically of the datatype array.
I have the following dataset:
task = {
content: "lorem....",
customer: [
{ id: 1, name: "hello" },
{ id: 2, name: "sup" },
],
end: "2020-08-13 10:09:48",
project: [{ id: 1 }, { id: 1 }, { id: 2 }],
vendor: [{ id: 2 }, { id: 2 }, { id: 3 }],
};
I wish to be able to dynamically check which of the objects (or nodes? and the algo has to recognize that it is an array) has duplicates, and reduce them to be in this form:
task = {
content: "lorem....",
customer: [
{ id: 1, name: "hello" },
{ id: 2, name: "sup" },
],
end: "2020-08-13 10:09:48",
project: [{ id: 1 }, { id: 2 }],
vendor: [{ id: 2 }, { id: 3 }],
};
EDIT
The algorithm needs to be able to handle a dynamic number of nodes (example 1), however , the duplicates will only happen 1 level down (Thanks for pointing out).
example 1 (there is 1 less node here ) :
task = {
content: "lorem....",
customer: [
{ id: 1, name: "hello" },
{ id: 2, name: "sup" },
],
end: "2020-08-13 10:09:48",
project: [{ id: 1 }, { id: 2 }],
};
Here is my proposed solution to remove duplicate elements from any array in the task object:
const uniq = array => {
const map = {};
const result = [];
for (let i = 0; i < array.length; i++) {
// since elements can be objects, need to do a deep comparison.
const element = JSON.stringify(array[i]);
if (map[element] === undefined) {
map[element] = true;
result.push(array[i]);
}
}
return result;
}
const task = {
content: "lorem....",
customer: [
{ id: 1, name: "hello" },
{ id: 2, name: "sup" },
],
end: "2020-08-13 10:09:48",
project: [{ id: 1 }, { id: 1 }, { id: 2 }],
vendor: [{ id: 2 }, { id: 2 }, { id: 3 }],
};
for (const key in task) {
if (Array.isArray(task[key])) {
task[key] = uniq(task[key])
}
}
console.log('deduped:', task);

Issue with js loops

I need help, I’m new to js and have to do this task. I’m confused what I’m doing wrong…
var products = [
product = {
id: 1,
name: "green",
},
product = {
id: 2,
name: "red",
},
product = {
id: 3,
name: "black",
},
];
var myWishlist = [
wishlist = {
id: 1,
productId: 4,
},
wishlist = {
id: 2,
productId: 2,
},
wishlist = {
id: 3,
productId: 2,
},
];
for (var i = 0; i < myWishlist.length; ++i) {
var currentWishlistProductId = myWishlist[i].productId;
for (var j = 0; j < products.length; ++j) {
var currentProductId = products[i].id;
if (currentWishlistProductId == currentProductId) {
console.log(
"Whishlist id: " +
myWishlist[i].id +
"Product name: " +
products[i].name,
);
}
}
}
Now output is: Whishlist id: 2 Product name: red
Output should look like this:
Whishlist id: 2 Product name: red
Whishlist id: 3 Product name: red
First of all, you need a data structure which is free of syntactic errors. You may have a look to Object initializer and put the objects inside of an Array without assigning to a variable (which makes no sense).
The a good idea is to use a data structure which gives the opportunity to have a fast access to data with a key, like an Object or Map. The later one accepts any type of variable as key and as value.
At last, you need only a single loop and get the wanted property from the mapped object.
var products = [{ id: 1, name: "green" }, { id: 2, name: "red" }, { id: 3, name: "black" }],
myWishlist = [{ id: 1, productId: 4 }, { id: 2, productId: 2 }, { id: 3, productId: 2 }],
productsMap = new Map(products.map(o => [o.id, o]));
for (var i = 0; i < myWishlist.length; ++i) {
console.log("Whishlist id:", myWishlist[i].id, "Product name:", (productsMap.get(myWishlist[i].productId) || {}).name);
}
Try this code below:
var products = [{ id: 1, name: "green" }, { id: 2, name: "red" }, { id: 3, name: "black" }],
myWishlist = [{ id: 1, productId: 4 }, { id: 2, productId: 2 }, { id: 3, productId: 2 }],
res = products.map(function (item) {
myWishlist.map(function (wishItem) {
if(item.id == wishItem.productId){
console.log("Whishlist id: "+wishItem.id+" Product name: "+item.name)
}
});
});
console.log(res)
Use "j" iterator for products array
var products = [
product = {
id: 1,
name: "green",
},
product = {
id: 2,
name: "red",
},
product = {
id: 3,
name: "black",
},
];
var myWishlist = [
wishlist = {
id: 1,
productId: 4,
},
wishlist = {
id: 2,
productId: 2,
},
wishlist = {
id: 3,
productId: 2,
},
];
for (var i = 0; i < myWishlist.length; ++i) {
var currentWishlistProductId = myWishlist[i].productId;
for (var j = 0; j < products.length; ++j) {
var currentProductId = products[j].id; // change i-> j
if (currentWishlistProductId == currentProductId) {
console.log(
"Whishlist id: " +
myWishlist[i].id +
"Product name: " +
products[j].name, // Change i->j
);
}
}
}

Find duplicate value object JS [duplicate]

This question already has answers here:
merge partially duplicated arrays in javascript (lodash)
(4 answers)
Group array items using object
(19 answers)
Closed 3 years ago.
I have a problem with javascript code
I have an array of the type
var array = [{
name: "Name 1",
id: 1
},
{
name: "Name 2",
id: 2
},
{
name: "Name 3",
id: 3
},
{
name: "Name 1",
id: 4
},
{
name: "Name 1",
id: 5
},
{
name: "Name 2",
id: 6
},
];
I'd like to get this:
var newArray = [{
name: "Name 1",
id: [1, 4, 5]
},
{
name: "Name 2",
id: [2, 6]
},
{
name: "Name 3",
id: 3
},
];
But I can't
I tried with a .find() but it doesn't work
Can you give me some leads please
You can use .reduce() for that. This example produces exactly the same output you expect:
var array = [
{
name: "Name 1",
id: 1
},
{
name: "Name 2",
id: 2
},
{
name: "Name 3",
id: 3
},
{
name: "Name 1",
id: 4
},
{
name: "Name 1",
id: 5
},
{
name: "Name 2",
id: 6
}
];
var output = array.reduce(function(res, curr) {
var existing = res.find(function(el) { return el.name === curr.name; });
if (existing) {
if (Array.isArray(existing.id))
existing.id.push(curr.id);
else
existing.id = [existing.id, curr.id]
} else {
res.push(curr);
}
return res;
}, []);
console.log(output);
You can use reduce() to create an object and then use Object.values to get an array. You can use map() after this to remove the array for those elements which have only a single id.
var array = [{
name: "Name 1",
id: 1
},
{
name: "Name 2",
id: 2
},
{
name: "Name 3",
id: 3
},
{
name: "Name 1",
id: 4
},
{
name: "Name 1",
id: 5
},
{
name: "Name 2",
id: 6
},
];
const res = Object.values(array.reduce((ac, a) => {
if(!ac[a.name]){
ac[a.name] = {...a, id: []}
}
ac[a.name].id.push(a.id);
return ac;
},{})).map(x => ({...x, id: x.id.length === 1 ? x.id[0] : x.id}))
console.log(res)
You can use reduce with a Map, for O(n) performance, as there are no nested loops:
const array = [
{ name: "Name 1", id: 1 },
{ name: "Name 2", id: 2 },
{ name: "Name 3", id: 3 },
{ name: "Name 1", id: 4 },
{ name: "Name 1", id: 5 },
{ name: "Name 2", id: 6 }
]
const out = [...array.reduce((a, o) => {
const e = a.get(o.name)
return (a.set(o.name, e ? Array.isArray(e) ? e.concat(o.id): [e, o.id] : o.id), a)
}, new Map())].map(([k, v]) => ({ name: k, id: v }))
console.log(out)
Try with Array.reduce() like this :
var array = [{
name: "Name 1",
id: 1
},
{
name: "Name 2",
id: 2
},
{
name: "Name 3",
id: 3
},
{
name: "Name 1",
id: 4
},
{
name: "Name 1",
id: 5
},
{
name: "Name 2",
id: 6
},
];
var output = array.reduce((acc, current) => {
if (exist = acc.find(p => p.name == current.name)) {
if(!Array.isArray(exist.id)){
exist.id = [exist.id];
}
exist.id.push(current.id);
} else {
acc.push(current)
}
return acc;
}, []);
console.log(output);

Flattering objects + arrays + objects into one object javascript [duplicate]

This question already has answers here:
How can I access and process nested objects, arrays, or JSON?
(31 answers)
Closed 5 years ago.
I will go straight to the point, so here is what I have:
const someObj = {
one: [
{
id: 123,
text: "lalala"
},
{
id: 456,
text: "lalala2"
},
{
id: 789,
text: "lalala3"
}
],
two: [
{
id: 111,
text: "text random"
},
{
id: 222,
text: "text random2"
},
{
id: 333,
text: "text random3"
}
]
};
and this is what I need to have:
const someOtherObj = {
111: {
id: 111,
text: "text random"
},
222: {
id: 222,
text: "text random2"
},
333: {
id: 333,
text: "text random3"
},
123: {
id: 123,
text: "lalala"
},
456: {
id: 456,
text: "lalala2"
},
789: {
id: 789,
text: "lalala3"
}
};
I know this can be achieved without million loops, just I can't think of any smart solution. :/ So, maybe someone can help me to solve this puzzle? :)
Thanks :)
Try with Array#reduce function with ES6
first reduce created array with all inner Object
Second reduce used to create object key with id
const someObj = { one: [ { id: 123, text: "lalala" }, { id: 456, text: "lalala2" }, { id: 789, text: "lalala3" } ], two: [ { id: 111, text: "text random" }, { id: 222, text: "text random2" }, { id: 333, text: "text random3" } ] };
var res = Object.values(someObj).reduce((a,b)=> (b.forEach(val=> a.push(val)),a),[])
var f = res.reduce((a,b)=> (a[b.id] = b, a),{})
console.log(f)
You only need to use two loops, no more (using ES6 seeing that your example used it as well)
const newObj = {};
for(const key in someObj) {
for(let i = 0; i < someObj[key].length; i++) {
const obj = someObj[key][i];
newObj[obj.id] = {
id: obj.id,
text: obj.text
}
}
}

Categories

Resources