I have some data and I need a loop which creates 2 arrays...
So I first create the 2 arrays:
namelist = [];
countList = [];
{
"id": "622",
"name": "main",
"sub": {
"637": {
"id": "637",
"name": "name 1",
"stats": {
"count": 5
}
},
"638": {
"id": "638",
"name": "name 2",
"stats": {
"count": 10
}
}
}
}
The desired result for this example would be:
For namelist:
['name 1', 'name 2']
For countList:
[5, 10]
How can I do this?
var nameList = [];
var countList = [];
var myObj =
{
"id": "622",
"name": "main",
"sub": {
"637": {
"id": "637",
"name": "name 1",
"stats": {
"count": 5
}
},
"638": {
"id": "638",
"name": "name 2",
"stats": {
"count": 10
}
}
}
};
for(var key in myObj.sub){
nameList.push(myObj.sub[key].name);
countList.push(myObj.sub[key].stats.count);
}
console.log(nameList);
console.log(countList);
for(var key in obj.sub){
nameList.push(obj.sub[key].name);
countList.push(obj.sub[key].stats.count;
}
Object.keys may help you to walk through object properties. Example related to your object:
var namelist = [],
countList = [],
obj = {
"id": "622",
"name": "main",
"sub": {
"637": {
"id": "637",
"name": "name 1",
"stats": {
"count": 5
}
},
"638": {
"id": "638",
"name": "name 2",
"stats": {
"count": 10
}
}
}
};
Object.keys(obj.sub).forEach(function(item) {
namelist.push(obj.sub[item].name);
countList.push(obj.sub[item].stats.count);
});
console.log(namelist, countList);
Working example: https://jsfiddle.net/ry0zqweL/
Obviously, you can optimise it in many ways. It's just illustrating one of the many solutions.
Related
I need some help on how to remove items from a TreeView (it's a Vue.js project), the TreeView is build based on an element like that:
[
{
"id": 1,
"name": "COMERCIALIZAÇÃO",
"idp": "",
"children": [
{
"id": 5,
"name": "Pasta 1",
"idp": 1,
"children": [
{
"id": 6,
"name": "Pasta 1 2",
"idp": 5,
"children": [
{
"id": 7,
"name": "NO.FT.DRC.01.00.001.pdf",
"file": "pdf",
"idp": 6
},
{
"id": 8,
"name": "PR.FT.DRC.01.00.003.pdf",
"file": "pdf",
"idp": 6
}
]
},
{
"id": 9,
"name": "imprimir p luiza.pdf",
"file": "pdf",
"idp": 5
},
{
"id": 66,
"name": "Pasta 1 3",
"idp": 5,
"children": [
{
"id": 77,
"name": "NO.FT.DRC.01.00.001.pdf",
"file": "pdf",
"idp": 66
},
{
"id": 88,
"name": "PR.FT.DRC.01.00.003.pdf",
"file": "pdf",
"idp": 66
}
]
}
]
},
{
"id": 10,
"name": "Backend.docx",
"file": "pdf",
"idp": 1
},
{
"id": 0,
"name": "DT.DC.RPI.03.03.1235_V2.docx",
"file": "pdf",
"idp": 1
}
]
},
{
"id": 2,
"name": "DISTRIBUIÇÃO",
"idp": "",
"children": [
{
"id": 11,
"name": "Pasta 2",
"idp": 2,
"children": [
{
"id": 12,
"name": "pasta 2 1",
"idp": 11,
"children": [
{
"id": 13,
"name": "script.sql",
"file": "pdf",
"idp": 12
}
]
}
]
}
]
},
{
"id": 3,
"name": "GERAÇÃO",
"idp": "",
"children": [
{
"id": 14,
"name": "Pasta 3",
"idp": 3
}
]
},
{
"id": 4,
"name": "SERVIÇOS",
"idp": "",
"children": [
{
"id": 5,
"name": "teste",
"idp": 4
}
]
}
]
I'm not sure, but I think that the best way to describe that element is: array of mutidimensional arrays, right?
I've created a CodePen to show the closest I got when using recursivity, but surely mine isn't the best solution since it doesn't work on every delete. Take a look at my code: https://codepen.io/luizarusso/pen/zYxLOPb?editors=1010
for (let i = 0; i < items.length; i++) {
if (items[i].id == item.id) {
//se achou o cara que vai ser removido, chama a função de remover
return this.removeItem(i);
} else {
if (items[i].children) {
if (items[i].idp == "") {
this.caminho = [];
}
this.caminho.push(i);
this.delFile(item, items[i].children);
} else {
if (items.length == 1 + i) {
this.caminho.pop();
}
}
}
}
Any ideas? Feel free to optimize my code directly on CodePen if you prefer :)
EDIT: Just to clarify, my problem here is strictly on how to remove an element by the id. When the user clicks on the bin icon I know what element I need to remove, but I don't know how to take it off of the array. Map, Filter and other native JS functions cannot do that to an array of arrays/JSON, so I tought about using recursivity or something else to make it work.
You need to look at objects, not just arrays.
Let me recommend an example library. https://github.com/leezng/vue-json-pretty.
If your question about multidimensional array iteration and process i think you have to ask on javascript and/or algorithm tags.
I hope this answer will help you.
The problem was with where I placed the this.caminho.pop()
I should only do that in the "else" of the condition that compares the id of the current item with the id of the item I'm looking for.
delFile(item, items) {
for (let i = 0; i < items.length; i++) {
if (items[i].id == item.id) {
//if the current item has the same id as the item I'm looking for
//it means I found the guy and I call the function to remove it
return this.removeItem(i);
} else {
//otherwise, I keep on searching
if (items[i].children) {
//if the item on the actual index have children, I'll search among them
if (items[i].idp == "") {
//if the items doesn't have a parent, I clean the "caminho" (path) var. That var traces the route till the item I'm looking for
this.caminho = [];
}
//I push the index to the var that traces the route
this.caminho.push(i);
//I call the function back again, now with the child items
this.delFile(item, items[i].children);
}
if (items.length == 1 + i) {
//if the item's lenght has been completely coursed, I pop the index out of the var that holds the route, because at this point I know the item I'm looking for is not among them
this.caminho.pop()
}
}
}
},
Here is the solution: https://codepen.io/luizarusso/pen/zYxLOPb
Works with treeview with any deepness
I have data and function like this:
const lodash = require('lodash')
var data = [
{
"nextStep": [
{
"nextStep": [
{
"nextStep": [
{
"nextStep": [],
"student": {
"name": "Alice",
"grade": 1
}
}
],
"student": {
"name": "Lisa",
"grade": 2
}
}
],
"student": {
"grade": 3,
"name": "This is GS"
}
}
],
"student": {
"grade": 4,
"name": "Paul"
}
}
]
function searchByJsonPath(path, obj, target) {
for (var k in obj) {
if (obj.hasOwnProperty(k))
if (k === target)
return path;
else if (typeof obj[k] === "object") {
var result = searchByJsonPath(path + "." + k, obj[k], target);
if (result)
return result;
}
}
return false;
}
I want to get the last item in object, the result should be
"name": "Alice",
"grade": 1
So I call the searchByJsonPath to get the path and use the lodash to get an item
test = searchByJsonPath('data', data, 'name');
but test = data.0.nextStep.0.nextStep.0.nextStep.0.student
the correct path should be data[0].nextStep[0].nextStep[0].nextStep[0].student
Please advice me.
You can try recursion like below to get the deepest element
var data = [{ "nextStep": [ { "nextStep": [ { "nextStep": [ { "nextStep": [], "student": { "name": "Alice", "grade": 1 } } ], "student": { "name": "Lisa", "grade": 2 } } ], "student": { "grade": 3, "name": "This is GS" } } ], "student": { "grade": 4, "name": "Paul" }}]
function getData(obj) {
return obj.nextStep.length > 0
? getData(obj.nextStep[0])
: obj.student
}
console.log(getData(data[0]))
var data = [
{
"text": "BEHIND A COMMON MEAL: POLYPHENOLS IN FOOD ",
"id": "445",
"parentid": ""
},
{
"text": "2.2 First Course: Pasta With Tomato Sauce (Polyphenols in Wheat Bran and Tomato Byproducts)",
"id": "441",
"parentid": "445"
},
{
"text": "2.3 A Fresh Side Dish: Mixed Salad (Polyphenols From Fennel, Carrot)",
"id": "442",
"parentid": "445"
},
{
"text": "hello mr.sujai",
"id": "448",
"parentid": "445"
},
{
"text": "polyhierarchy",
"id": "449",
"parentid": "445"
},
{
"text": "INTRODUCTION",
"id": "452",
"parentid": ""
},
{
"text": "1.2 The Tight Biochemical Connection Between Vegetables and Their Byproducts",
"id": "440",
"parentid": "452"
},
{
"text": "OTHER OFF-THE-MENU MISCELLANEOUS",
"id": "454",
"parentid": ""
},
{
"text": "SOMETHING TO DRINK",
"id": "456",
"parentid": ""
},
{
"text": "3.1 Orange Juice (Polyphenols From Orange Byproducts)",
"id": "443",
"parentid": "456"
},
{
"text": "3.2 Wine (Polyphenols From Grape and Wine Byproducts)",
"id": "444",
"parentid": "456"
},
{
"text": "understandings",
"id": "451",
"parentid": "456"
},
{
"text": "Polyphenols",
"id": "453",
"parentid": "451"
},
{
"text": "this is test",
"id": "458",
"parentid": "455"
},
{
"text": "polyhierarchy",
"id": "449",
"parentid": "458"
},
{
"text": "hello",
"id": "447",
"parentid": "449"
},
{
"text": "hi",
"id": "459",
"parentid": "447"
},
{
"text": "polyhierarchy",
"id": "449",
"parentid": "459"
},
{
"text": "testing",
"id": "457",
"parentid": "458"
},
{
"text": "hi test",
"id": "450",
"parentid": "457"
},
{
"text": "speech",
"id": "446",
"parentid": "450"
}]
function jsonTree() {
// Keep a fast lookup dictionary
var dictionary = {};
for (var i = 0; i < data.length; i++) {
dictionary[data[i].id] = data[i];
}
for (var i = 0; i < data.length; i++) {
if (data[i].parentid == 449) {
var test = "";
}
if (data[i].parentid) {
var parent = dictionary[data[i].parentid];
arrData = parent;
if (parent) {
if (!parent.children) {
parent.children = [];
}
parent.children.push(data[i]);
// arrData.children.push(data[i]);
}
}
}
var arrData = [];
for (var i = 0; i < data.length; i++) {
if (data[i].parentid == 455) {
arrData.push(data[i]);
}
}
document.getElementById("test").innerHTML = JSON.stringify(arrData);
return false;
}
polyhierarchy term having different parent.
for (var i = 0; i < data.length; i++) {
dictionary[data[i].id] = data[i];
}
in this place same id is replaced. polyhierarchy having id is 449. when add to dictionary it is replaced.
Tree structure should be
1. BEHIND A COMMON MEAL: POLYPHENOLS IN FOOD
polyhierarchy
2. this is test
polyhierarchy
hello
hi
polyhierarchy
i need array with parent, child relationship.
There are a few mistakes.
You have duplicate id's for your polyhierarchie element. Because you're building a dictionary to lookup your ids, you're overwriting your child element the second/subsequent time you add it to your object.
{
"text": "polyhierarchy",
"id": "449", //<-- duplicate
"parentid": "459"
}
You have non existant parentIds.
{
"text": "SOMETHING TO DRINK",
"id": "456",
"parentid": "455" // <--- doesn't exist
}
The code got a little more complex than anticipated because of those two issues.
function mapData (data) {
//build a dictionary for: id -> [eles]
var map = data.reduce ((obj, ele) => {
obj[ele.id] = [ //let's make the lookup an array, to support multiple elements with the same id
...obj[ele.id] || [], //keep the existing elements or initialize it to an array
{...ele, children: []}
];
return obj
}, {});
return Object.keys (map).reduce ((arr, key) => {
let eles = map [key] || []; //process all elements
eles.forEach (ele => {
let parents = map [ele.parentid] || [];
let parent = parents [0];
if (!parent) {
parent = map [ele.parentid] = {children: [], root: true}
}
parent.children.push (ele);
if (parent.root && !~arr.indexOf (parent)) arr.push (parent);
});
return arr;
},[])
}
console.log (mapData (data))
I am trying to grab a value of a key inside of an object in an array which itself is an object in an array.
Here is what it looks like:
var books = [
{
"title": "title1",
"author": "author1",
"users": [
{
"id": 1,
"name": "Isidro"
},
{
"id": 4,
"name": "Jose Miguel"
},
{
"id": 3,
"name": "Trinidad"
}
]
},
{
"title": "title2",
"author": "author2",
"users": [
{
"id": 4,
"name": "Jose Miguel"
},
{
"id": 5,
"name": "Beatriz"
},
{
"id": 6,
"name": "Rosario"
}
]
},
What I am trying to do, 2 things:
First:
when I click on a user name in the HTML, I want to match the name clicked with the same user name in all the objects it is present in.
Second:
display the title of the books this user name is present in.
For example: when I click on Jose Miguel I want to see the 2 books he has read.
At the moment I have this:
var btnUser = document.querySelectorAll(".individualUsers");
for (var i = 0; i < btnUser.length; i++) {
btnUser[i].addEventListener("click", function() {
var clickedUser = this.innerText
var userBooks = books
.filter(x => x.users.name.indexOf(clickedUser) > -1)
.map(x => ` <li>${x.title}</li> <li>${x.author}</li>`);
console.log(clickedUser);
});
}
My problem is x.users.name.indexOf(clickedUser)is not accessing the user name.
You need to search inside the users array as well, one neat way is to do so with Array.some that return true if some of the conditional is true.
const books = [{
"title": "title1",
"author": "author1",
"users": [{
"id": 1,
"name": "Isidro"
},
{
"id": 4,
"name": "Jose Miguel"
},
{
"id": 3,
"name": "Trinidad"
}
]
},
{
"title": "title2",
"author": "author2",
"users": [{
"id": 4,
"name": "Jose Miguel"
},
{
"id": 5,
"name": "Beatriz"
},
{
"id": 6,
"name": "Rosario"
}
]
}
];
const clickedUser = 'Jose Miguel';
var userBooks = books
.filter(x => x.users.some(user => user.name.indexOf(clickedUser) > -1));
console.log(userBooks);
Am having an arrray of Objects which again contains the id's of the parent Object:
eg:-
$scope.result=[
{
"id": 1,
"name": ABC,
"type": PQR,
"parentId": 2
},
{
"id": 2,
"name": ABC,
"type": PQR,
"parentId": 1
}]
I would like to convert this JSON in to the following wherin I will be having the parentObject in place of parentId's
$scope.result=[
{
"id": 1,
"name": ABC,
"type": a,
"parentId": {
"id": 2,
"name": PQR,
"type": b,
"parentId": 1
}
},
{
"id": 2,
"name": PQR,
"type": b,
"parentId": {
"id": 1,
"name": ABC,
"type": a
}
}
]
Can anybody help me with this conversion..
Assuming parentId will reference to one element
angular.forEach($scope.result, function(result) {
var obj = $scope.result.filter(function(ele) {
return result.parentId === ele.id;
})[0];
result.parentId = obj;
});
Since your tags doesn't contain angularjs, I'm using Array.prototype.forEach here
$scope.result.forEach(function(result) {
var obj = $scope.result.filter(function(ele) {
return result.parentId === ele.id;
})[0];
result.parentId = obj;
});
Will do 2 loops first one to fill a hash with keys of the ids, second will loop to replace parent id with actual object:
$scope = {}
$scope.result=[
{
"id": 1,
"name": "ABC",
"type": "PQR",
"parentId": 2
},
{
"id": 2,
"name": "ABC",
"type": "PQR",
"parentId": 1
}]
parents = {}
for(i=0;i<$scope.result.length;i++){
parents[$scope.result[i]["id"]] = jQuery.extend({}, $scope.result[i]); // Clone object
}
for(i=0;i<$scope.result.length;i++){
$scope.result[i]["parentId"] = parents[$scope.result[i]["parentId"]]
}
$scope.result