This question already has answers here:
How can I access and process nested objects, arrays, or JSON?
(31 answers)
From an array of objects, extract value of a property as array
(24 answers)
Loop through an array in JavaScript
(46 answers)
Closed 2 years ago.
So I'm building some content with Formio and it has the ability to add custom JSON content for the drop down options.
This is my JSON:
[
{
"MBB": [
{
"Name": "BYO Sim"
},
{
"Name": "Device Sim"
},
{
"Name": "Apple Watch"
},
{
"Name": "Samsung Watch"
}
],
"WB": [
{
"Name": "4G with Device"
},
{
"Name": "4G without Device"
},
{
"Name": "5G"
}
]
}
]
What I want to do is show all values that are under MBB:Name
I have found that when I enter the below, I get the value "Device Sim" returned but I want to return all values under MBB and Name as I will soon be adding more options, not just Name.
item.MBB[1].Name
If I just do:
item.MBB.Name
I just get an undefined outcome so I'm a little lost.
Any help would be appreciated!
You need a function to extract an array of just Name from the array of objects, each of which contains its own Name.
item.MBB.map(obj => obj.Name)
You can remove the first array:
{
"MBB": [
{
"Name": "BYO Sim"
},
{
"Name": "Device Sim"
},
{
"Name": "Apple Watch"
},
{
"Name": "Samsung Watch"
}
],
"WB": [
{
"Name": "4G with Device"
},
{
"Name": "4G without Device"
},
{
"Name": "5G"
}
]
}
Use map method of the array for the iteration.
const data =
{
"MBB": [
{
"Name": "BYO Sim"
},
{
"Name": "Device Sim"
},
{
"Name": "Apple Watch"
},
{
"Name": "Samsung Watch"
}
],
"WB": [
{
"Name": "4G with Device"
},
{
"Name": "4G without Device"
},
{
"Name": "5G"
}
]
}
;
const result = data['MBB'].map(({Name}) => Name);
console.log(result);
Related
I have a following JSON Structure which I need to parse in React to build a side menu for an app.
var a = [
{"name":"John",
"subMenus":[{"First":[{"name":"Vulnerability","to":"/johnvulner"},
{"name":"Open Roles","to":"/johnopenRoles"}
]},
{"Second":[{"name":"Some People","to":"/johnpeople"},
{"name":"Another People","to":"/johnanotherpeople"}
]}],
},
{"name":"Sarah",
"subMenus":[{"First":[{"name":"Vulnerability","to":"/sarahvulner"},
{"name":"Open Roles","to":"/sarahopenRoles"}
]},
{"Second":[{"name":"Some People","to":"/sarahsomepeople"},
{"name":"Another People","to":"/sarahanotherpeople"}
]}],
}];
The output needed for the nested side menu should be as follows -
John
First
Vulnerability
Open Roles
Second
Some People
Another People
Sarah
First
Vulnerability
Open Roles
Second
Some People
Another People
Is there a simple way using array.map function to achieve this since I am building this menu inside an HTML div.
You can create it very easily by using the following code
let a = [{
"name": "John",
"subMenus": [{
"First": [{
"name": "Vulnerability",
"to": "/johnvulner"
},
{
"name": "Open Roles",
"to": "/johnopenRoles"
}
]
},
{
"Second": [{
"name": "Some People",
"to": "/johnpeople"
},
{
"name": "Another People",
"to": "/johnanotherpeople"
}
]
}
],
},
{
"name": "Sarah",
"subMenus": [{
"First": [{
"name": "Vulnerability",
"to": "/sarahvulner"
},
{
"name": "Open Roles",
"to": "/sarahopenRoles"
}
]
},
{
"Second": [{
"name": "Some People",
"to": "/sarahsomepeople"
},
{
"name": "Another People",
"to": "/sarahanotherpeople"
}
]
}
],
}
];
var menuItems = []
a.map((menu) => {
var submenus = []
menu.subMenus.map((submenu) => {
let keys = Object.keys(submenu);
keys.map( key => {
var keyValues=[]
if (submenu[key]){
submenu[key].map((item) => {
keyValues.push(item.name)
})
submenus.push({
[key]: keyValues
})
}
})
})
let thekey=menu.name
menuItems.push({
[thekey]: submenus
})
})
console.log(menuItems)
Update: Code updated for a any key fetch..
I have a types variable that is an array of objects. Each object has 2 properties name and content.
The second property content is an array of object with only one property : name.
When displayed in the template with {{types}} I see this:
[ { "name": "Base", "content": [ { "name": "Base (Lager/Pilsner)" }, { "name": "Base (Pale)" }, { "name": "Base (Pale Ale)" }, { "name": "Base (Wheat)" }, { "name": "Base (Rye" }, { "name": "Base (Wheat)" } ] },
{ "name": "Kilned", "content": [ { "name": "Munich" }, { "name": "Vienna" }, { "name": "Aromatic" }, { "name": "Amber|Biscuit|Victory" }, { "name": "Brown Malt" } ] },
{ "name": "Stewed", "content": [ { "name": "Caramel|Crystal" }, { "name": "Dextrin" }, { "name": "Special Belge" }, { "name": "Honey Malt" } ] },
{ "name": "Roasted/Torrefied", "content": [ { "name": "Pale Chocolate" }, { "name": "Chocolate" }, { "name": "Black Wheat" }, { "name": "Roast Barley" }, null, { "name": "Roast Rye" }, { "name": "BLack Malt" } ] },
{ "name": "Others", "content": [ { "name": "Acidulated" } ] } ]
Here is my template
<div class="h-3/4 overflow-auto">
<div v-for="(group,index) in types">
<FermentableTypeItem
#updateModel="updateModel"
:key="index"
:type_name="group.name"
:group_name="group.name"
:state="group.state"
></FermentableTypeItem>
{{group.content}}
<FermentableTypeItem
v-for=" (t,index) in group.content"
#updateModel="updateModel"
:key="index"
:type_name="t.name"
:group_name="group.name"
></FermentableTypeItem>
</div>
</div>
As you can see I want to add a special [1] FermentableTypeItem for each first level element and then loop on this first level element 's content property to add a list of normal [2] FermentableTypeItem.
Note 1: special means that the group_name and the type_name are
identical
Note 2: normal means the the group_name and the type_name are
different
It works and display the various FermentableTypeItem s but only when I don't use the t variable in the second loop
If I use it, the app crashes saying the t is undefined.
Could somebody help me fixing this error ? May be it's obvious but I cannot see what is wrong.
There is null content object present. So remove null content from response your or check null v-if="t != null" like below.
<div v-for=" (t,index) in group.content" :index="index">
<FermentableTypeItem v-if="t != null"
#updateModel="updateModel"
:key="index"
:type_name="t.name"
:group_name="group.name"
></FermentableTypeItem>
</div>
I am trying to filter out a nested array of objects using lodash which is pretty straightforward but I am looking to avoid multiple calls.
I am looking to create 2 array of objects using a single lodash call/function. Looking to find object property "$isMultiAccount" if it exists put the whole object into one result set and if not put it to another ruleset.
Currently I am doing this with Lodash "has and filter" for first and for other "!has" which means same object is looped twice , as object is relatively large its creating bottleneck for speed
https://repl.it/repls/HomelyExpensiveTruetype
const item = {
"domains": [
{
"id": "dm11022",
"information":{
"description": "Customer",
"owner": {
"primary":{
"name": "James",
"phone": "NA"
},
"others": [
{
"$isMultiAccount": "./Yes"
}
]
}
}
},
{
"id": "dm12022",
"information":{
"description": "Customer",
"owner": {
"primary":{
"name": "James",
"phone": "NA"
},
"others": [
{
"$isMultiAccount": "./No"
}
]
}
}
},
{
"id": "dm12022",
"information":{
"description": "Customer",
"owner": {
"primary":{
"name": "James",
"phone": "NA"
},
"others": [
{
"conf": {
"isVpnBased":{
"accountType": "Primary"
}
}
}
]
}
}
}
]
}
/*
Expected result
output1 = [
{
"id": "dm11022",
"information":{
"description": "Customer",
"owner": {
"primary":{
"name": "James",
"phone": "NA"
},
"others": [
{
"$isMultiAccount": "./Yes"
}
]
}
}
},
{
"id": "dm12022",
"information":{
"description": "Customer",
"owner": {
"primary":{
"name": "James",
"phone": "NA"
},
"others": [
{
"$isMultiAccount": "./No"
}
]
}
}
}
]
// $isMultiAccount account do not exist in this object
output2 = [
{
"id": "dm12022",
"information":{
"description": "Customer",
"owner": {
"primary":{
"name": "James",
"phone": "NA"
},
"others": [
{
"conf": {
"isVpnBased":{
"accountType": "Primary"
}
}
}
]
}
}
}
]
*/
const item = {
"domains": [
{
"id": "dm11022",
"information":{
"description": "Customer",
"owner": {
"primary":{
"name": "James",
"phone": "NA"
},
"others": [
{
"$isMultiAccount": "./Yes"
}
]
}
}
},
{
"id": "dm12022",
"information":{
"description": "Customer",
"owner": {
"primary":{
"name": "James",
"phone": "NA"
},
"others": [
{
"$isMultiAccount": "./No"
}
]
}
}
},
{
"id": "dm12022",
"information":{
"description": "Customer",
"owner": {
"primary":{
"name": "James",
"phone": "NA"
},
"others": [
{
"conf": {
"isVpnBased":{
"accountType": "Primary"
}
}
}
]
}
}
}
]
}
const [areMulti, areNotMulti] = _.reduce(item.domains, (current, next) => {
return _.has(next, ‘information.owner.others.$isMultiAccount’)
? [current[0].concat(next), current[1]]
: [current[0], current[1].concat(next)];
}, [[], []]);
console.log(areMulti);
console.log(areNotMulti);
Since item.domains.information.owner.others is an array, you need to tackle it as follows:
let multi = [];
let notMulti = [];
_.each(item.domains, function (obj) {
if (obj.information.owner.others.length && _.has(obj.information.owner.others[0], '$isMultiAccount'))
multi.push(obj);
else
notMulti.push(obj);
});
console.log(multi);
console.log(notMulti);
Unfortunately, you have to iterate over the domains array as well ass on the owner.others array to determine if the object with specific key sits inside.
So the algorithm has O(n*m) complexity.
If you ask for a lodash function seems that the partition method is what you're looking for
As docs says:
Creates an array of elements split into two groups, the first of which contains elements predicate returns truthy for, the second of which contains elements predicate returns falsey for. The predicate is invoked with one argument: (value).
So it will be like:
_.partition(
item.domains,
e => _.some(
_.get(e, 'information.owner.others'),
el => _.has(el,"$isMultiAccount")
)
);
Watch out - some hack available!
However, if the you're 100% sure that the element you're looking for will be always at specific index (for example it is supposed to be always as first element - so index 0) you can limit the algorithm to have linear complexity O(n) as only the size of the domains array will matter in terms of performance.
The hackish solution assuming fixed array index=0:
_.partition(
item.domains,
e => _.has(e, 'information.owner.others.0.$isMultiAccount')
);
NOTE
Using lodash makes code a bit easier to read but of course it creates some performance overhead anyway.
I would like to get the opposite GraphQL query field:
which mean the query string will not appeal in the result, while not inside the query string will appeal in the result.
Because there are varties of json recorders, I can not manually write opposite query. Any way to write opposite query automatically?
for example, I have JSON like:
{
"data": {
"source": "AWS",
"hero": {
"version": "my version",
"name": "R2-D2",
"friends": [
{
"attribute": "like something",
"name": "Luke Skywalker"
},
{
"name": "Han Solo"
},
{
"name": "Leia Organa"
}
]
}
}
}
I have query
{
source,
hero {
name
friends {
attribute
}
}
}
I like to get a result:
{
"data": {
"hero": {
"version": "my version",
"friends": [
{
"name": "Luke Skywalker"
},
{
"name": "Han Solo"
},
{
"name": "Leia Organa"
}
]
}
}
}
Which the query fields not in the query will appear in the result, while the query fields in the query will not inside the result.
How to do these operations in JavaScript? Can you give me an example?
You only get the fields you include in the Query if you want to get whats not in the query then write another query for the fields not in the original query.
At its simplest, GraphQL is about asking for specific fields on objects.
https://graphql.org/learn/queries/
Query:
{
hero {
version
friends {
name
}
}
}
Result:
{
"data": {
"hero": {
"version": "my version",
"friends": [
{
"name": "Luke Skywalker"
},
{
"name": "Han Solo"
},
{
"name": "Leia Organa"
}
]
}
}
}
Update from comments:
Your question is more of how to Dynamically Generate GraphQL Queries?
In this case you could use fragments, but you would still have to write multiple queries.
Fragments let you construct sets of fields, and then include them in queries where you need to.
https://graphql.org/learn/queries/#fragments
This question already has answers here:
Remove duplicates in an object array Javascript
(10 answers)
Closed 5 years ago.
I have an array containing arrays of objects which I need to compare.
I've looked through multiple similar threads, but I couldn't find a proper one that compares multiple arrays of objects (most are comparing two arrays of objects or just comparing the objects within a single array)
This is the data (below is a JSFiddle with code sample)
const data = [
[
{
"id": "65",
"name": "Some object name",
"value": 90
},
{
"id": "89",
"name": "Second Item",
"value": 20
}
],
[
{
"id": "89",
"name": "Second Item",
"value": 20
},
{
"id": "65",
"name": "Some object name",
"value": 90
}
],
[
{
"id": "14",
"name": "Third one",
"value": 10
}
]
]
I want to remove all duplicate arrays of objects, regardless of the length of data (there could be a lot more records).
I managed to get the unique ones extracted into an object:
const unique = data.reduce(function(result, obj) {
return Object.assign(result, obj)
}, [])
That doesn't work for me though, because I need 1 of the duplicated arrays to remain and the returned data to be an array as well, instead of an object. E.g.:
// result I need
[
[
{
"id":"65",
"name":"Some object name",
"value":90
},
{
"id":"89",
"name":"Second Item",
"value":20
}
],
[
{
"id":"14",
"name":"Third one",
"value":10
}
]
]
So how do I compare each array of objects to the others in the parent array and preserve one of each duplicated or unique array of objects?
JSFiddle
you can achieve so by using function.As below. Not sure about best optimum way of doing so.
var testArray = [
[
{
"id": "65",
"name": "Some object name",
"value": 90
},
{
"id": "89",
"name": "Second Item",
"value": 20
}
],
[
{
"id": "89",
"name": "Second Item",
"value": 20
},
{
"id": "65",
"name": "Some object name",
"value": 90
}
],
[
{
"id": "14",
"name": "Third one",
"value": 10
}
]
]
function removeDuplicatesFromArray(arr){
var obj={};
var uniqueArr=[];
for(var i=0;i<arr.length;i++){
if(!obj.hasOwnProperty(arr[i])){
obj[arr[i]] = arr[i];
uniqueArr.push(arr[i]);
}
}
return uniqueArr;
}
var newArr = removeDuplicatesFromArray(testArray);
console.log(newArr);
const data = [
[
{
"id": "65",
"name": "Some object name",
"value": 90
},
{
"id": "89",
"name": "Second Item",
"value": 20
}
],
[
{
"id": "89",
"name": "Second Item",
"value": 20
},
{
"id": "65",
"name": "Some object name",
"value": 90
}
],
[
{
"id": "14",
"name": "Third one",
"value": 10
}
]
];
const temp = {};
const result = [];
data.forEach(itemArr => {
const items = itemArr.filter(item => {
const isUnique = temp[`${item.id}-${item.name}-${item.value}`] === undefined;
temp[`${item.id}-${item.name}-${item.value}`] = true;
return isUnique;
});
if (items.length !== 0)
result.push(items);
});
console.log(result);