How can I read agent_code from this string with JavaScript? And please explain me the logic.
JSON (one-line):
[{"name":"NYC","zone_id":"1","totalagents":"40","agents":[{"id":"1","agent_code":"====="},{"id":"2","agent_code":"====="},{"id":"3","agent_code":"Christian"},{"id":"4","agent_code":"Tom"},{"id":"5","agent_code":"Dave Damsky"},{"id":"6","agent_code":"====="},{"id":"7","agent_code":"Andrew"},{"id":"8","agent_code":"Paolo"},{"id":"9","agent_code":"Josh"},{"id":"10","agent_code":"Shipster Van"},{"id":"11","agent_code":"====="},{"id":"16","agent_code":"Christian2"},{"id":"20","agent_code":"Nathan"},{"id":"21","agent_code":"Aaron"},{"id":"22","agent_code":"Rob"},{"id":"23","agent_code":"Taylor"},{"id":"24","agent_code":"Drea"},{"id":"25","agent_code":"Mario "},{"id":"26","agent_code":"Julio"},{"id":"27","agent_code":"Abbas"},{"id":"28","agent_code":"Ahmed"},{"id":"29","agent_code":"David Damsky"},{"id":"30","agent_code":"Micheal"},{"id":"31","agent_code":"Moe"},{"id":"32","agent_code":"Luis"},{"id":"33","agent_code":"Darin"},{"id":"37","agent_code":"Alan"},{"id":"39","agent_code":"Cristian Marte"},{"id":"40","agent_code":"Cody"},{"id":"41","agent_code":"David Pinto"},{"id":"42","agent_code":"Will "},{"id":"44","agent_code":"Evan"},{"id":"45","agent_code":"Santiago"},{"id":"46","agent_code":"John"},{"id":"47","agent_code":"Moubeen"},{"id":"49","agent_code":"Devin Armstrong"},{"id":"50","agent_code":"Marco Bell"},{"id":"51","agent_code":"Youness Benzaid"},{"id":"52","agent_code":"Amin Mechouche"},{"id":"53","agent_code":"Franco Herrera"}]}]
JSON (formatted):
[
{
"name": "NYC",
"zone_id": "1",
"totalagents": "40",
"agents": [
{
"id": "1",
"agent_code": "====="
},
{
"id": "2",
"agent_code": "====="
},
{
"id": "3",
"agent_code": "Christian"
},
{
"id": "4",
"agent_code": "Tom"
},
{
"id": "5",
"agent_code": "Dave Damsky"
},
{
"id": "6",
"agent_code": "====="
},
{
"id": "7",
"agent_code": "Andrew"
},
{
"id": "8",
"agent_code": "Paolo"
},
{
"id": "9",
"agent_code": "Josh"
},
{
"id": "10",
"agent_code": "Shipster Van"
},
{
"id": "11",
"agent_code": "====="
},
{
"id": "16",
"agent_code": "Christian2"
},
{
"id": "20",
"agent_code": "Nathan"
},
{
"id": "21",
"agent_code": "Aaron"
},
{
"id": "22",
"agent_code": "Rob"
},
{
"id": "23",
"agent_code": "Taylor"
},
{
"id": "24",
"agent_code": "Drea"
},
{
"id": "25",
"agent_code": "Mario "
},
{
"id": "26",
"agent_code": "Julio"
},
{
"id": "27",
"agent_code": "Abbas"
},
{
"id": "28",
"agent_code": "Ahmed"
},
{
"id": "29",
"agent_code": "David Damsky"
},
{
"id": "30",
"agent_code": "Micheal"
},
{
"id": "31",
"agent_code": "Moe"
},
{
"id": "32",
"agent_code": "Luis"
},
{
"id": "33",
"agent_code": "Darin"
},
{
"id": "37",
"agent_code": "Alan"
},
{
"id": "39",
"agent_code": "Cristian Marte"
},
{
"id": "40",
"agent_code": "Cody"
},
{
"id": "41",
"agent_code": "David Pinto"
},
{
"id": "42",
"agent_code": "Will "
},
{
"id": "44",
"agent_code": "Evan"
},
{
"id": "45",
"agent_code": "Santiago"
},
{
"id": "46",
"agent_code": "John"
},
{
"id": "47",
"agent_code": "Moubeen"
},
{
"id": "49",
"agent_code": "Devin Armstrong"
},
{
"id": "50",
"agent_code": "Marco Bell"
},
{
"id": "51",
"agent_code": "Youness Benzaid"
},
{
"id": "52",
"agent_code": "Amin Mechouche"
},
{
"id": "53",
"agent_code": "Franco Herrera"
}
]
}
]
Lets say your above is a json string
var jsonString = '[{"name":"NYC","zone_id":"1","totalagents":"40","agents":[{"id":"1","agent_code":"====="},{"id":"2","agent_code":"====="},{"id":"3","agent_code":"Christian"},{"id":"4","agent_code":"Tom"},{"id":"5","agent_code":"Dave Damsky"},{"id":"6","agent_code":"====="},{"id":"7","agent_code":"Andrew"},{"id":"8","agent_code":"Paolo"},{"id":"9","agent_code":"Josh"},{"id":"10","agent_code":"Shipster Van"},{"id":"11","agent_code":"====="},{"id":"16","agent_code":"Christian2"},{"id":"20","agent_code":"Nathan"},{"id":"21","agent_code":"Aaron"},{"id":"22","agent_code":"Rob"},{"id":"23","agent_code":"Taylor"},{"id":"24","agent_code":"Drea"},{"id":"25","agent_code":"Mario "},{"id":"26","agent_code":"Julio"},{"id":"27","agent_code":"Abbas"},{"id":"28","agent_code":"Ahmed"},{"id":"29","agent_code":"David Damsky"},{"id":"30","agent_code":"Micheal"},{"id":"31","agent_code":"Moe"},{"id":"32","agent_code":"Luis"},{"id":"33","agent_code":"Darin"},{"id":"37","agent_code":"Alan"},{"id":"39","agent_code":"Cristian Marte"},{"id":"40","agent_code":"Cody"},{"id":"41","agent_code":"David Pinto"},{"id":"42","agent_code":"Will "},{"id":"44","agent_code":"Evan"},{"id":"45","agent_code":"Santiago"},{"id":"46","agent_code":"John"},{"id":"47","agent_code":"Moubeen"},{"id":"49","agent_code":"Devin Armstrong"},{"id":"50","agent_code":"Marco Bell"},{"id":"51","agent_code":"Youness Benzaid"},{"id":"52","agent_code":"Amin Mechouche"},{"id":"53","agent_code":"Franco Herrera"}]}]';
var json = JSON.parse(jsonString); // parse string into json
Now as this json is an array with length 1, to get all agent code you will have to do something like this.
for (var i = 0; i <json[0].agents.length; i++) {
console.log(json[0].agents[i].agent_code);
}
Related
I'm newbie and sequelize aggregate function makes me confused because it gave me different result than expected. I'm trying to get a total price with sequelize.fn('sum', ...), and somehow sequelize only gives me the the total of first data of the associated model instead of summing all the result. My code as follows:
Training.findAll({
where: {
owner_id: payload
},
attributes: ['id', [sequelize.fn('sum', sequelize.col('training_classes.price')), 'totalPrice']],
include: [{
model: TrainingClass,
as: 'training_classes',
attributes: ['id', 'price'],
}],
group: ['Training.id', 'training_classes.id']
})
And the result of the query :
[
{
"id": "45",
"totalPrice": "300000",
"training_classes": [
{
"id": "94",
"price": "300000"
}
]
},
{
"id": "8",
"totalPrice": "1000000",
"training_classes": [
{
"id": "14",
"price": "1000000"
},
{
"id": "15",
"price": "300000"
},
{
"id": "16",
"price": "200000"
}
]
},
{
"id": "47",
"totalPrice": "100000",
"training_classes": [
{
"id": "97",
"price": "100000"
}
]
},
{
"id": "39",
"totalPrice": "1000000",
"training_classes": [
{
"id": "81",
"price": "1000000"
},
{
"id": "82",
"price": "300000"
}
]
},
{
"id": "24",
"totalPrice": "300000",
"training_classes": [
{
"id": "46",
"price": "300000"
}
]
},
{
"id": "6",
"totalPrice": "200000",
"training_classes": [
{
"id": "11",
"price": "200000"
}
]
},
{
"id": "49",
"totalPrice": "100000",
"training_classes": [
{
"id": "100",
"price": "100000"
},
{
"id": "99",
"price": "1000000"
},
{
"id": "101",
"price": "100000"
}
]
},
{
"id": "20",
"totalPrice": "200000",
"training_classes": [
{
"id": "38",
"price": "200000"
},
{
"id": "35",
"price": "400000"
},
{
"id": "37",
"price": "500000"
},
{
"id": "36",
"price": "100000"
}
]
},
]
as you can see, the totalPrice only from the first element of training_classes, not the entire data of it. How can I resolve this? Thank you in advance
If you want to sum all records in TrainingClass that have the same Training.id then you need to indicate no attributes for TrainingClass and indicate only Training.id in group option:
Training.findAll({
where: {
owner_id: payload
},
attributes: ['id', [sequelize.fn('sum', sequelize.col('training_classes.price')), 'totalPrice']],
include: [{
model: TrainingClass,
as: 'training_classes',
attributes: [],
}],
group: ['Training.id']
})
If you group by TrainingClass.id then you'll get grouped results for each record that has unique TrainingClass.id value and literally every record of TrainingClass has unique id value.
so I am trying to figure out how I can possible scrape a javascript tag using regex which I believe might be the easiest way.
The tag looks like:
<script type="text/javascript">
var spConfig=newApex.Config({
"attributes": {
"199": {
"id": "199",
"code": "legend",
"label": "Weapons",
"options": [
{
"label": "10",
"priceInGame": "0",
"id": [
]
},
{
"label": "10.5",
"priceInGame": "0",
"id": [
]
},
{
"label": "11",
"priceInGame": "0",
"id": [
"66659"
]
},
{
"label": "11.5",
"priceInGame": "0",
"id": [
]
},
{
"label": "12",
"priceInGame": "0",
"id": [
]
},
{
"label": "12.5",
"priceInGame": "0",
"id": [
]
},
{
"label": "13",
"priceInGame": "0",
"id": [
]
},
{
"label": "4",
"priceInGame": "0",
"id": [
]
},
{
"label": "4.5",
"priceInGame": "0",
"id": [
]
},
{
"label": "5",
"priceInGame": "0",
"id": [
]
},
{
"label": "5.5",
"priceInGame": "0",
"id": [
]
},
{
"label": "6",
"priceInGame": "0",
"id": [
]
},
{
"label": "6.5",
"priceInGame": "0",
"id": [
]
},
{
"label": "7",
"priceInGame": "0",
"id": [
]
},
{
"label": "7.5",
"priceInGame": "0",
"id": [
]
},
{
"label": "8",
"priceInGame": "0",
"id": [
"66672"
]
},
{
"label": "8.5",
"priceInGame": "0",
"id": [
"66673"
]
},
{
"label": "9",
"priceInGame": "0",
"id": [
]
},
{
"label": "9.5",
"priceInGame": "0",
"id": [
"66675"
]
}
]
}
},
"weaponID": "66733",
"chooseText": "Apex Legends",
"Config": {
"includeCoins": false,
}
});
</script>
and I want to scrape all Label
Whaht I tried to do is:
for nosto_sku_tag in bs4.find_all('script', {'type': 'text/javascript'}):
try:
test = re.findall('var spConfig = (\{.*}?);', nosto_sku_tag.text.strip())
print(test)
except: # noqa
continue
but it only returned an empty value of []
so I am here asking what can I do to be able to scrape the labels?
You need to specify the attribute using attr=value or attrs={'attr': 'value'} syntax.
https://www.crummy.com/software/BeautifulSoup/bs4/doc/#the-keyword-arguments
import json
import re
from bs4 import BeautifulSoup
if __name__ == '__main__':
html = '''
<script type="text/javascript">
var spConfig=newApex.Config({
"attributes": {
"199": {
"id": "199",
"code": "legend",
"label": "Weapons",
"options": [
{ "label": "10", "priceInGame": "0", "id": [] },
{ "label": "10.5", "priceInGame": "0", "id": [] },
{ "label": "11", "priceInGame": "0", "id": [ "66659" ] },
{ "label": "7.5", "priceInGame": "0", "id": [] },
{ "label": "8", "priceInGame": "0", "id": ["66672"] }
]
}
},
"weaponID": "66733",
"chooseText": "Apex Legends",
"taxConfig": {
"includeCoins": false,
}
});
</script>
'''
soup = BeautifulSoup(html, 'html.parser')
# this one works too
# script = soup.find('script', attrs={'type':'text/javascript'})
script = soup.find('script', type='text/javascript')
js: str = script.text.replace('\n', '')
raw_json = re.search('var spConfig=newApex.Config\(({.*})\);', js, flags=re.MULTILINE).group(1)
data = json.loads(raw_json)
labels = [opt['label'] for opt in data['attributes']['199']['options']]
print(labels)
output:
['10', '10.5', '11', '7.5', '8'] ... some removed for brevity
If you are just looking for the entire row field in the JSON object, use the following;
("label":) "([^"]+)",
Then if you want to return the actual value, just use
\2
to pull back the second group
I have a hierarchy tree JSON with multiple level of nesting. When i am trying to loop through the JSON for displaying tree structure in UI. I am ending up with cyclic redundancy since parent ID is same at different level. I need to add unique identifiers for parentID and ID, so in recursive call it does not end up in infinite loop.
Sample JSON :
[
{
"id": "12",
"text": "Man"
},
{
"id": "6",
"parentId": "12",
"text": "Boy"
},
{
"id": "9",
"parentId": "6",
"text": "Boy-Boy"
},
{
"id": "13",
"parentId": "9",
"text": "Boy-Boy-Boy"
},
{
"id": "7",
"parentId": "12",
"text": "Other"
},
{
"id": "6",
"parentId": "7",
"text": "Boy"
},
{
"id": "9",
"parentId": "6",
"text": "Boy-Boy"
},
{
"id": "13",
"parentId": "9",
"text": "Boy-Boy-Boy"
}
I have tried by adding depth to each level but not able to maintain the ParentId and Id relationship.
var depthArray = []
function addDepth(arr, depth = 0) {
arr.forEach(obj => {
obj.id = obj.id + '-' + depth;
if(obj.children !== undefined) {
addDepth(obj.children, depth + 1)
}})
return arr;
}
[
{
"id": "12",
"text": "Man"
},
{
"id": "6",
"parentId": "12",
"text": "Boy"
},
{
"id": "9",
"parentId": "6",
"text": "Boy-Boy"
},
{
"id": "13",
"parentId": "9",
"text": "Boy-Boy-Boy"
},
{
"id": "7",
"parentId": "12",
"text": "Other"
},
{
"id": "6-1",
"parentId": "7",
"text": "Boy"
},
{
"id": "9-1",
"parentId": "6-1",
"text": "Boy-Boy"
},
{
"id": "13-1",
"parentId": "9-1",
"text": "Boy-Boy-Boy"
}
]
Your recursion does not work, what about this ?
But not sure how to rename IDs:
'use strict';
function addDepth(arr, id, depth) {
if(depth === undefined) depth = 0;
if(id !== undefined)
arr.forEach(obj => {
if(id == obj.parentId) {
if(depth) obj.parentId += '-' + depth;
addDepth(arr, obj.id, depth + 1)
}
})
else arr.forEach(obj => { addDepth(arr, obj.id, depth); });
return arr;
}
console.log(addDepth(
[
{
"id": "12",
"text": "Man"
},
{
"id": "6",
"parentId": "12",
"text": "Boy"
},
{
"id": "9",
"parentId": "6",
"text": "Boy-Boy"
},
{
"id": "13",
"parentId": "9",
"text": "Boy-Boy-Boy"
},
{
"id": "7",
"parentId": "12",
"text": "Other"
},
{
"id": "6",
"parentId": "7",
"text": "Boy"
},
{
"id": "9",
"parentId": "6",
"text": "Boy-Boy"
},
{
"id": "13",
"parentId": "9",
"text": "Boy-Boy-Boy"
}
]
));
Hard to guess how structure may look like, but made a supposed output by hand and then similar code - looking up only (not sure how to distinguish same records with parentId difference):
12 Man
12 6 Man Boy
12 6 9 Man Boy Boy-Boy
12 6 9 13 Man Boy Boy-Boy Boy-Boy-Boy
12 7 Man Other
12 7 Man Other Boy
12 7 6 9 Man Other Boy Boy-Boy
12 7 6 9 13 Man Other Boy Boy-Boy Boy-Boy-Boy
var data = GetData();
var arr = [data[0].text], parent;
for(var i=0;i<data.length;i++) {
if(parent = data[i].parentId) {
arr.push(data[i].text); // we have parentId, so iterate back
for(var j=i;j >= 0;j--) {
if(data[j].id == parent) {
arr.push(data[j].text); // & colect text properties
if(data[j].parentId) {
parent = data[j].parentId;
j = i;
}
}
}
}
console.log(arr.reverse().join(" -> "));
arr = [];
}
function GetData() { return [
{
"id": "12",
"text": "Man"
},
{
"id": "6",
"parentId": "12",
"text": "Boy"
},
{
"id": "9",
"parentId": "6",
"text": "Boy-Boy"
},
{
"id": "13",
"parentId": "9",
"text": "Boy-Boy-Boy"
},
{
"id": "7",
"parentId": "12",
"text": "Other"
},
{
"id": "6",
"parentId": "7",
"text": "Boy"
},
{
"id": "9",
"parentId": "6",
"text": "Boy-Boy"
},
{
"id": "13",
"parentId": "9",
"text": "Boy-Boy-Boy"
}
];
}
How can i filter an array of objects like the one down below based on the 'id' or the 'subdivisions.id'
ps: the ids are unique and you can not find object.id == object.subdivisions[n].id
{
"id": "1",
"name": "South East",
"subdivisions": [
{
"id": "2",
"name": "Berkshire"
},
{
"id": "3",
"name": "Buckinghamshire"
},
{
"id": "4",
"name": "East Sussex"
},
{
"id": "5",
"name": "Hampshire"
},
{
"id": "6",
"name": "Isle of Wight"
},
{
"id": "7",
"name": "Kent"
},
{
"id": "8",
"name": "Oxfordshire"
},
{
"id": "9",
"name": "Surrey"
},
{
"id": "10",
"name": "West Sussex"
}
]
}
and get as a result a simple object like this:
{
"id": "10",
"name": "West Sussex"
}
Edit
here is the full array:
[
{
"id": "1",
"name": "South East",
"subdivisions": [
{
"id": "2",
"name": "Berkshire",
"__typename": "Region"
},
{
"id": "3",
"name": "Buckinghamshire",
"__typename": "Region"
},
{
"id": "4",
"name": "East Sussex",
"__typename": "Region"
},
{
"id": "5",
"name": "Hampshire",
"__typename": "Region"
},
{
"id": "6",
"name": "Isle of Wight",
"__typename": "Region"
},
{
"id": "7",
"name": "Kent",
"__typename": "Region"
},
{
"id": "8",
"name": "Oxfordshire",
"__typename": "Region"
},
{
"id": "9",
"name": "Surrey",
"__typename": "Region"
},
{
"id": "10",
"name": "West Sussex",
"__typename": "Region"
}
],
"__typename": "Region"
},
{
"id": "11",
"name": "London",
"subdivisions": [
{
"id": "12",
"name": "City of London",
"__typename": "Region"
},
{
"id": "13",
"name": "City of Westminster",
"__typename": "Region"
},
{
"id": "14",
"name": "Kensington and Chelsea",
"__typename": "Region"
},
{
"id": "15",
"name": "Hammersmith and Fulham",
"__typename": "Region"
},
{
"id": "16",
"name": "Wandsworth",
"__typename": "Region"
},
{
"id": "17",
"name": "Lambeth",
"__typename": "Region"
},
{
"id": "18",
"name": "Southwark",
"__typename": "Region"
},
{
"id": "19",
"name": "Tower Hamlets",
"__typename": "Region"
},
{
"id": "20",
"name": "Hackney",
"__typename": "Region"
},
{
"id": "21",
"name": "Islington",
"__typename": "Region"
},
{
"id": "22",
"name": "Camden",
"__typename": "Region"
},
{
"id": "23",
"name": "Brent",
"__typename": "Region"
},
{
"id": "24",
"name": "Ealing",
"__typename": "Region"
},
{
"id": "25",
"name": "Hounslow",
"__typename": "Region"
},
{
"id": "26",
"name": "Richmond",
"__typename": "Region"
},
{
"id": "27",
"name": "Kingston",
"__typename": "Region"
},
{
"id": "28",
"name": "Merton",
"__typename": "Region"
},
{
"id": "29",
"name": "Sutton",
"__typename": "Region"
},
{
"id": "30",
"name": "Croydon",
"__typename": "Region"
},
{
"id": "31",
"name": "Bromley",
"__typename": "Region"
},
{
"id": "32",
"name": "Lewisham",
"__typename": "Region"
},
{
"id": "33",
"name": "Greenwich",
"__typename": "Region"
},
{
"id": "34",
"name": "Bexley",
"__typename": "Region"
},
{
"id": "35",
"name": "Havering",
"__typename": "Region"
},
{
"id": "36",
"name": "Barking and Dagenham",
"__typename": "Region"
},
{
"id": "37",
"name": "Redbridge",
"__typename": "Region"
},
{
"id": "38",
"name": "Newham",
"__typename": "Region"
},
{
"id": "39",
"name": "Waltham Forest",
"__typename": "Region"
},
{
"id": "40",
"name": "Haringey",
"__typename": "Region"
},
{
"id": "41",
"name": "Enfield",
"__typename": "Region"
},
{
"id": "42",
"name": "Barnet",
"__typename": "Region"
},
{
"id": "43",
"name": "Harrow",
"__typename": "Region"
},
{
"id": "44",
"name": "Hillingdon",
"__typename": "Region"
}
],
"__typename": "Region"
},
{
"id": "45",
"name": "North West England",
"subdivisions": [
{
"id": "46",
"name": "Cheshire",
"__typename": "Region"
},
{
"id": "47",
"name": "Cumbria",
"__typename": "Region"
},
{
"id": "48",
"name": "Greater Manchester",
"__typename": "Region"
},
{
"id": "49",
"name": "Lancashire",
"__typename": "Region"
},
{
"id": "50",
"name": "Merseyside",
"__typename": "Region"
}
],
"__typename": "Region"
},
{
"id": "51",
"name": "East of England",
"subdivisions": [
{
"id": "52",
"name": "East Anglia",
"__typename": "Region"
},
{
"id": "53",
"name": "Bedfordshire and Hertfordshire",
"__typename": "Region"
},
{
"id": "54",
"name": "Essex",
"__typename": "Region"
}
],
"__typename": "Region"
},
{
"id": "55",
"name": "West Midlands",
"subdivisions": [
{
"id": "56",
"name": "Herefordshire, Worcestershire and Warwickshire",
"__typename": "Region"
},
{
"id": "57",
"name": "Shropshire and Staffordshire",
"__typename": "Region"
},
{
"id": "58",
"name": "West Midlands",
"__typename": "Region"
}
],
"__typename": "Region"
},
{
"id": "59",
"name": "South West England",
"subdivisions": [
{
"id": "60",
"name": "Gloucestershire, Wiltshire and Bristol/Bath area",
"__typename": "Region"
},
{
"id": "61",
"name": "Dorset and Somerset",
"__typename": "Region"
},
{
"id": "62",
"name": "Cornwall and Isles of Scilly",
"__typename": "Region"
},
{
"id": "63",
"name": "Devon",
"__typename": "Region"
}
],
"__typename": "Region"
},
{
"id": "64",
"name": "Yorkshire and the Humber",
"subdivisions": [
{
"id": "65",
"name": "East Riding and North Lincolnshire",
"__typename": "Region"
},
{
"id": "66",
"name": "North Yorkshire",
"__typename": "Region"
},
{
"id": "67",
"name": "South Yorkshire",
"__typename": "Region"
},
{
"id": "68",
"name": "West Yorkshire",
"__typename": "Region"
}
],
"__typename": "Region"
},
{
"id": "69",
"name": "East Midlands",
"subdivisions": [
{
"id": "70",
"name": "Derbyshire and Nottinghamshire",
"__typename": "Region"
},
{
"id": "71",
"name": "Leicestershire, Rutland and Northamptonshire",
"__typename": "Region"
},
{
"id": "72",
"name": "Lincolnshire",
"__typename": "Region"
}
],
"__typename": "Region"
},
{
"id": "73",
"name": "North East England",
"subdivisions": [
{
"id": "74",
"name": "Tees Valley and County Durham",
"__typename": "Region"
},
{
"id": "75",
"name": "Northumberland and Tyne and Wear",
"__typename": "Region"
}
],
"__typename": "Region"
}
]
You could use Array#find for it.
let result = object.subdivisions.find(sub => sub.id === id);
For a search either outside or in subdivisions, you could use the following
function find(data, id) {
var result = data.find(o => o.id === id);
if (!result) {
data.some(o => result = o.subdivisions.find(s => s.id === id));
}
return result;
}
var data = [{ id: "1", name: "South East", subdivisions: [{ id: "2", name: "Berkshire", __typename: "Region" }, { id: "3", name: "Buckinghamshire", __typename: "Region" }, { id: "4", name: "East Sussex", __typename: "Region" }, { id: "5", name: "Hampshire", __typename: "Region" }, { id: "6", name: "Isle of Wight", __typename: "Region" }, { id: "7", name: "Kent", __typename: "Region" }, { id: "8", name: "Oxfordshire", __typename: "Region" }, { id: "9", name: "Surrey", __typename: "Region" }, { id: "10", name: "West Sussex", __typename: "Region" }], __typename: "Region" }, { id: "11", name: "London", subdivisions: [{ id: "12", name: "City of London", __typename: "Region" }, { id: "13", name: "City of Westminster", __typename: "Region" }, { id: "14", name: "Kensington and Chelsea", __typename: "Region" }, { id: "15", name: "Hammersmith and Fulham", __typename: "Region" }, { id: "16", name: "Wandsworth", __typename: "Region" }, { id: "17", name: "Lambeth", __typename: "Region" }, { id: "18", name: "Southwark", __typename: "Region" }, { id: "19", name: "Tower Hamlets", __typename: "Region" }, { id: "20", name: "Hackney", __typename: "Region" }, { id: "21", name: "Islington", __typename: "Region" }, { id: "22", name: "Camden", __typename: "Region" }, { id: "23", name: "Brent", __typename: "Region" }, { id: "24", name: "Ealing", __typename: "Region" }, { id: "25", name: "Hounslow", __typename: "Region" }, { id: "26", name: "Richmond", __typename: "Region" }, { id: "27", name: "Kingston", __typename: "Region" }, { id: "28", name: "Merton", __typename: "Region" }, { id: "29", name: "Sutton", __typename: "Region" }, { id: "30", name: "Croydon", __typename: "Region" }, { id: "31", name: "Bromley", __typename: "Region" }, { id: "32", name: "Lewisham", __typename: "Region" }, { id: "33", name: "Greenwich", __typename: "Region" }, { id: "34", name: "Bexley", __typename: "Region" }, { id: "35", name: "Havering", __typename: "Region" }, { id: "36", name: "Barking and Dagenham", __typename: "Region" }, { id: "37", name: "Redbridge", __typename: "Region" }, { id: "38", name: "Newham", __typename: "Region" }, { id: "39", name: "Waltham Forest", __typename: "Region" }, { id: "40", name: "Haringey", __typename: "Region" }, { id: "41", name: "Enfield", __typename: "Region" }, { id: "42", name: "Barnet", __typename: "Region" }, { id: "43", name: "Harrow", __typename: "Region" }, { id: "44", name: "Hillingdon", __typename: "Region" }], __typename: "Region" }, { id: "45", name: "North West England", subdivisions: [{ id: "46", name: "Cheshire", __typename: "Region" }, { id: "47", name: "Cumbria", __typename: "Region" }, { id: "48", name: "Greater Manchester", __typename: "Region" }, { id: "49", name: "Lancashire", __typename: "Region" }, { id: "50", name: "Merseyside", __typename: "Region" }], __typename: "Region" }, { id: "51", name: "East of England", subdivisions: [{ id: "52", name: "East Anglia", __typename: "Region" }, { id: "53", name: "Bedfordshire and Hertfordshire", __typename: "Region" }, { id: "54", name: "Essex", __typename: "Region" }], __typename: "Region" }, { id: "55", name: "West Midlands", subdivisions: [{ id: "56", name: "Herefordshire, Worcestershire and Warwickshire", __typename: "Region" }, { id: "57", name: "Shropshire and Staffordshire", __typename: "Region" }, { id: "58", name: "West Midlands", __typename: "Region" }], __typename: "Region" }, { id: "59", name: "South West England", subdivisions: [{ id: "60", name: "Gloucestershire, Wiltshire and Bristol/Bath area", __typename: "Region" }, { id: "61", name: "Dorset and Somerset", __typename: "Region" }, { id: "62", name: "Cornwall and Isles of Scilly", __typename: "Region" }, { id: "63", name: "Devon", __typename: "Region" }], __typename: "Region" }, { id: "64", name: "Yorkshire and the Humber", subdivisions: [{ id: "65", name: "East Riding and North Lincolnshire", __typename: "Region" }, { id: "66", name: "North Yorkshire", __typename: "Region" }, { id: "67", name: "South Yorkshire", __typename: "Region" }, { id: "68", name: "West Yorkshire", __typename: "Region" }], __typename: "Region" }, { id: "69", name: "East Midlands", subdivisions: [{ id: "70", name: "Derbyshire and Nottinghamshire", __typename: "Region" }, { id: "71", name: "Leicestershire, Rutland and Northamptonshire", __typename: "Region" }, { id: "72", name: "Lincolnshire", __typename: "Region" }], __typename: "Region" }, { id: "73", name: "North East England", subdivisions: [{ id: "74", name: "Tees Valley and County Durham", __typename: "Region" }, { id: "75", name: "Northumberland and Tyne and Wear", __typename: "Region" }], __typename: "Region" }];
console.log(find(data, 'foo')); // undefined
console.log(find(data, '66')); // item from subdivisions
console.log(find(data, '69')); // item from outer array
.as-console-wrapper { max-height: 100% !important; top: 0; }
I grab a list of data from the server and I have to convert it.
Part of this is turning it into a 3 dimensional array. After the "myArr[i].children.push(temp);" it leaves copies of the objects that were pushed in the root of the array. Can I either push without copying or how would I delete these? (I have underscore js included, I know they have good array functions :))
for (var i = 0; i < myArr.length; i++) {
myArr[i].children = [];
for (var q = 0; q < myArr.length; q++) {
if (myArr[i].id == myArr[q].parentid) {
var temp = {
id: myArr[q].id,
index: myArr[q].index,
text: myArr[q].text
}
myArr[i].children.push(temp);
};
};
};
The Data
[{
"id": "5",
"parentid": "0",
"text": "Device Guides",
"index": "0"
}, {
"id": "6",
"parentid": "0",
"text": "Pre-Sales Evaluation",
"index": "1"
}, {
"id": "7",
"parentid": "0",
"text": "Router Setup Guides",
"index": "2"
}, {
"id": "9",
"parentid": "7",
"text": "Sonicwall",
"index": "0"
}, {
"id": "10",
"parentid": "5",
"text": "Grandstream GXP-21XX",
"index": "1"
}, {
"id": "11",
"parentid": "5",
"text": "Polycom Soundstation\/Soundpoint",
"index": "2"
}, {
"id": "12",
"parentid": "7",
"text": "Cisco",
"index": "1"
}, {
"id": "15",
"parentid": "0",
"text": "Post-Sales Implementation Check List",
"index": "7"
}, {
"id": "16",
"parentid": "15",
"text": "Porting and New Number Details",
"index": "0"
}, {
"id": "18",
"parentid": "15",
"text": "Partner Setup",
"index": "1"
}, {
"id": "19",
"parentid": "15",
"text": "test",
"index": "2"
}, {
"id": "20",
"parentid": "0",
"text": "test",
"index": "11"
}, {
"id": "21",
"parentid": "15",
"text": "test",
"index": "3"
}, {
"id": "23",
"parentid": "5",
"text": "New Polycom",
"index": "0"
}, {
"id": "24",
"parentid": "0",
"text": "Test Markup",
"index": "14"
}, {
"id": "25",
"parentid": "0",
"text": "test",
"index": "15"
}]
After it is formated:
{
"children": [{
"id": "5",
"parentid": "0",
"text": "Device Guides",
"index": "1",
"children": [{
"id": "10",
"index": "0",
"text": "Grandstream GXP-21XX"
}, {
"id": "11",
"index": "1",
"text": "Polycom Soundstation/Soundpoint"
}, {
"id": "23",
"index": "2",
"text": "New Polycom"
}]
}, {
"id": "6",
"parentid": "0",
"text": "Pre-Sales Evaluation",
"index": "0",
"children": []
}, {
"id": "7",
"parentid": "0",
"text": "Router Setup Guides",
"index": "2",
"children": [{
"id": "9",
"index": "0",
"text": "Sonicwall"
}, {
"id": "12",
"index": "1",
"text": "Cisco"
}]
}, {
"id": "9",
"parentid": "7",
"text": "Sonicwall",
"index": "0",
"children": []
}, {
"id": "10",
"parentid": "5",
"text": "Grandstream GXP-21XX",
"index": "0",
"children": []
}, {
"id": "11",
"parentid": "5",
"text": "Polycom Soundstation/Soundpoint",
"index": "1",
"children": []
}, {
"id": "12",
"parentid": "7",
"text": "Cisco",
"index": "1",
"children": []
}, {
"id": "15",
"parentid": "0",
"text": "Post-Sales Implementation Check List",
"index": "7",
"children": [{
"id": "16",
"index": "0",
"text": "Porting and New Number Details"
}, {
"id": "18",
"index": "1",
"text": "Partner Setup"
}, {
"id": "19",
"index": "2",
"text": "test"
}, {
"id": "21",
"index": "3",
"text": "test"
}]
}, {
"id": "16",
"parentid": "15",
"text": "Porting and New Number Details",
"index": "0",
"children": []
}, {
"id": "18",
"parentid": "15",
"text": "Partner Setup",
"index": "1",
"children": []
}, {
"id": "19",
"parentid": "15",
"text": "test",
"index": "2",
"children": []
}, {
"id": "20",
"parentid": "0",
"text": "test",
"index": "11",
"children": []
}, {
"id": "21",
"parentid": "15",
"text": "test",
"index": "3",
"children": []
}, {
"id": "23",
"parentid": "5",
"text": "New Polycom",
"index": "2",
"children": []
}, {
"id": "24",
"parentid": "0",
"text": "Test Markup",
"index": "14",
"children": []
}, {
"id": "25",
"parentid": "0",
"text": "test",
"index": "15",
"children": []
}]
}
Here you go
tree = {0: {children: []}}
data.forEach(function(x) {
x.children = tree[x.id] ? tree[x.id].children : [];
tree[x.id] = x;
if(!tree[x.parentid])
tree[x.parentid] = {children: []}
tree[x.parentid].children.push(x)
})
result = tree[0].children
This solution is linear (iterates over the array just once) and doesn't require any pre-sorting.
http://jsfiddle.net/U47WY/
and here's how to convert the tree back to the linear array:
function flatten(source) {
return source.reduce(function(a, x) {
var children = x.children;
delete x.children;
return a.concat([x], flatten(x.children))
}, []);
}
Following on from a friendly discussion in the comments :
var zeroObj = {"children":[]};
for (var i = 0; i < myArr.length; i++) {
if(myArr[i].parentid === 0) {
zeroObj.children.push(myArr[i]);
} else {
for (var q = 0; q < myArr.length; q++) {
if (myArr[i].parentid == myArr[q].id) {
myArr[q].children = myArr[q].children || [];
myArr[q].children.push(myArr[i]);
};
};
}
};