I have an array of objects like this:
[
{
"id": 2,
"title": "LA COPA",
"parent_menu_id": nil
},
{
"id": 3,
"title": "CALENDARIO",
"parent_menu_id": nil
},
{
"id": 5,
"title": "Torneo",
"parent_menu_id": 2
},
{
"id": 6,
"title": "Nice",
"parent_menu_id": 2
}
]
This is the structure of a menu.
Each object is an menu item.
If the key "parent_menu_id" is nil, it means that the item is a parent menu.
If it has a value, is a children. I.E the third item means that item id: 5 is child of item id:2.
This is the desired output:
[
{
"id": 2,
"title": "LA COPA",
"active": true,
"parent_menu_id": nil,
"submenus":[
{
"id": 5,
"title": "Torneo",
"active": true,
"parent_menu_id": 2
},
{
"id": 6,
"title": "Nice",
"parent_menu_id": 2
}
]
},
{
"id": 3,
"title": "CALENDARIO",
"active": true,
"parent_menu_id": nil
}
]
I know the algorithm:
if pareny_menu_id is different than nill search the key id == parent_menu_id
If submenu key is not present, create it.
Move the child item to the parent.
Then delete the child item from base location.
But I am not sure about the methods to use..
Any ideas?
Cheers!
#!ruby
require 'pp'
objects = [
{
"id" => 2,
"title" => "LA COPA",
"parent_menu_id" => nil
},
{
"id" => 3,
"title" => "CALENDARIO",
"parent_menu_id" => nil
},
{
"id" => 5,
"title" => "Torneo",
"parent_menu_id" => 2
},
{
"id" => 6,
"title" => "Nice",
"parent_menu_id" => 2
}
]
objects.collect! do |child|
if not child["parent_menu_id"].nil? then
parents = objects.select{|o| o["id"] == child["parent_menu_id"]}
parents.each do |pr|
pr["submenus"] ||= []
pr["submenus"] << child
end
end
child
end.select!{|o| o["parent_menu_id"].nil? }
pp objects
output:
[{"id"=>2,
"title"=>"LA COPA",
"parent_menu_id"=>nil,
"submenus"=>
[{"id"=>5, "title"=>"Torneo", "parent_menu_id"=>2},
{"id"=>6, "title"=>"Nice", "parent_menu_id"=>2}]},
{"id"=>3, "title"=>"CALENDARIO", "parent_menu_id"=>nil}]
arr = [
{
id: 2,
title: "LA COPA",
parent_menu_id: nil
},
{
id: 3,
title: "CALENDARIO",
parent_menu_id: nil
},
{
id: 5,
title: "Torneo",
parent_menu_id: 2
},
{
id: 6,
title: "Nice",
parent_menu_id: 2
}
]
parents, children = arr.partition { |g| g[:parent_menu_id].nil? }
#= [[{:id=>2, :title=>"LA COPA", :parent_menu_id=>nil},
# {:id=>3, :title=>"CALENDARIO", :parent_menu_id=>nil}],
# [{:id=>5, :title=>"Torneo", :parent_menu_id=>2},
# {:id=>6, :title=>"Nice", :parent_menu_id=>2}]]
children.each do |child|
parent_id = child[:parent_menu_id]
parent = parents.find { |p| p[:id] == parent_id }
if parent.key?(:submenus)
parent[:submenus] << child
else
parent[:submenus] = [child.merge(active: true)]
end
end
parents
#=> [{:id=>2, :title=>"LA COPA", :parent_menu_id=>nil,
# :submenus=>[{:id=>5, :title=>"Torneo", :parent_menu_id=>2, :active=>true},
# {:id=>6, :title=>"Nice", :parent_menu_id=>2}]},
# {:id=>3, :title=>"CALENDARIO", :parent_menu_id=>nil}]
Notes:
"id": 2 is redundant. Just use id: 2. You only need quotes when the symbol is comprised of more than one word.
I assumed that the key value pair active: true is only present for the first element of the value (array) of :submenus.
Related
I have data from an API that is like:
[
{
"id": 1,
"name": "eventName1",
"related_events": [
2,
3
]
},
{
"id": 2,
"name": "eventName2",
"related_events": [
1,
3
]
},
{
"id": 3,
"name": "eventName3",
"related_events": [
1,
2,
4
]
}
]
Each element of the related_events array links to an id element. So, if the related_events has 2 and 3 then that means I have to call id 2 and 3.
If I want to get the name that corresponds to the related_events ids, how would I code it?
Example, if the related_events has 2 and 3 then I want to display the names "eventName2" and "eventName3".
You can search your data for the related_event ids by iterating through or by using Array.find function.
Something like this:
const testData = [
{
"id": 1,
"name": "eventName1",
"related_events": [
2,
3
]
},
{
"id": 2,
"name": "eventName2",
"related_events": [
1,
3
]
},
{
"id": 3,
"name": "eventName3",
"related_events": [
1,
2,
4
]
}
];
// the object to test from the data
const testObject = testData[0];
//we iterate over every id of related_events
testObject.related_events.forEach(targetId => {
//we search in the data for a matching element that corresponds to the related_event id
const targetElement = testData.find(element => {return element.id === targetId});
//check if that element actually exists, just to be sure
if (!!targetElement) {
console.log(targetElement.name);
}
else {
console.log("no matching object found");
}
});
There is really no difference when using React to just using basic javascript, as the logic is the same.
Suppose I have the following payload with nested array, how do I combine the array inside the nested array for the same externalId as well as some logic on certain field like
shipQty - this field will be sum or add up for records with the same externalId under fillingOrder
serialNumbers - all the records under serialNumbers will be display together if the externalId is same
Kindly refer below for the input and expected output
Json Payload Input
{
"Identifier": "9i098p-898j-67586k",
"transactionDate": "2019-09-08T10:01:00-04:00",
"order": [
{
"orderNumber": "123456789",
"CourierOrderId": "1300-88-2525",
"fillingOrder": [
{
"numberOfBoxes": 0,
"tracking": [
{
"carrier": "Orange",
"trackNum": "3333444",
"trackUrl": "https://www.orange.com/track/status",
"shipDate": "2019-09-08T10:01:00-04:00",
"SerialNumber": "00000123"
}
],
"row": [
{
"externalId": "1",
"unitNo": "OP04-123456-789",
"shipQty": 2,
"serialNumbers": [
{
"serialNumber": "USD333555",
"quantity": 1
},
{
"serialNumber": "USD235678",
"quantity": 1
}
]
}
]
},
{
"tracking": [
{
"carrier": "Apple",
"trackNum": "555666",
"trackUrl": "https://www.apple.com/track/status",
"shipDate": "2019-09-08T10:01:00-04:00",
"SerialNumber": "00000645"
}
],
"row": [
{
"externalId": "1",
"unitNo": "OP04-123456-789",
"shipQty": 3,
"serialNumbers": [
{
"serialNumber": "USD123456",
"quantity": 1
},
{
"serialNumber": "USD98765",
"quantity": 1
},
{
"serialNumber": "USD45689",
"quantity": 1
}
]
}
]
},
{
"tracking": [
{
"carrier": "banana",
"trackNum": "587390",
"trackUrl": "https://www.banana.com/track/status",
"shipDate": "2019-09-08T10:01:00-04:00",
"SerialNumber": "00000365"
}
],
"row": [
{
"externalId": "2",
"unitNo": "OP05-123456-111",
"shipQty": 2,
"serialNumbers": [
{
"serialNumber": "USD00045",
"quantity": 1
},
{
"serialNumber": "USD00046",
"quantity": 1
}
]
}
]
}
]
}
]
}
Expected Json Output
{
"row": [
{
"externalId": "1",
"unitNo": "OP04-123456-789",
"shipQty": 5, //the shipQty should be add up when the externalId is same
"serialNumbers": [ //the serialNumbers should display all the data inside the serialNumbers when the externalId is same
{
"serialNumber": "USD333555",
"quantity": 1
},
{
"serialNumber": "USD235678",
"quantity": 1
},
{
"serialNumber": "USD123456",
"quantity": 1
},
{
"serialNumber": "USD98765",
"quantity": 1
},
{
"serialNumber": "USD45689",
"quantity": 1
}
]
},
{
"externalId": "2",
"unitNo": "OP05-123456-111",
"shipQty": 2,
"serialNumbers": [
{
"serialNumber": "USD00045",
"quantity": 1
},
{
"serialNumber": "USD00046",
"quantity": 1
}
}
]
}
It looks like you only need the data of "row" inside the fillingOrder field of your payload. So first thing to simplicy the problem is to get all the rows as a single array. Once you have that them you just need to group that by external id and the problem will start to look smaller.
%dw 2.0
output application/json
//First get all rows since it looks like you only need them.
//If you find this confusing try to use flatten with some simpler payloads.
var allRows = flatten(flatten(payload.order.fillingOrder).row)
//Group them according to external id.
var groupedExtId = allRows groupBy $.externalId
---
{
row: groupedExtId pluck ((value, extId, index) -> do {
var sumShipQuant = sum(value.shipQty default [])
---
{
externalId: (extId), //the key after grouping is external id
unitNo: value.unitNo[0], //assuming it is same across diff external id
shipQty: sumShipQuant,
serialNumbers: flatten(value.serialNumbers) //Flatten because value is an array and it has multiple serielNumbers array
}
})
}
This should help. I took some inspiration from Harshank Bansal post
%dw 2.0
output application/json
var groupFlat = flatten(flatten (payload.order.fillingOrder).row) groupBy ($.externalId)
---
row: [groupFlat mapObject ((value, key, index) -> {
externalId: value.externalId[0],
unitNO: value.unitNo[0],
shipQty: sum(value.shipQty),
serialNumbers: flatten(value.serialNumbers)
})]
Try this:
%dw 2.0
output application/json
---
row:[ if (payload..order..row..externalId[0] == payload..order..row..externalId[1]) {
externalId : payload..order..row..externalId[0],
unitNo: payload..order..row..unitNo[0],
shipQty: payload..order..row..shipQty[0] + payload..order..row..shipQty[1],
serialNumbers: flatten (payload..order..row..serialNumbers)
}
else null]
I have a two arrays:
Users [
{ "id": 0, "name": "Scott" },
{ "id": 0, "name": "Jan" },
{ "id": 0, "name": "Jack" },
]
Users2Add [
{ "id": 0, "name": "Scott" },
{ "id": 0, "name": "Andy" },
{ "id": 0, "name": "John" },
]
I want to check if new users in Users2Add are already in Users array. If yes don't push(add to array) else add the new User(From User2Add) to Users array. Like:
forEach(var u in Users2Add ) {
if(!(Users.containts(x => x.id == User2Add.idx))) Users.push(u);
}
The problem is that there's no straightforward way to check object equality in JS, and of course:
{a: 1} === {a: 1} //false
A possible solution is to use lodash:
Users2Add.forEach(user => {
if (!Users.some(existingUser = > _.isEqual(existingUser, user))) {
Users.push(user);
}
});
i want to grouping data JSON (One JSON) base on region. and the json after grouping like in (Two JSON). and i use the two JSON for show data (Result JSON). so, how to add loop base on region after grouping, because actually i want to show data in front end like (Result JSON):
==>One JSON
data:[
{id:1,
status: "active",
dataDetail: {
id: 5,
name: tes 1,
region: aaa,
}
},
{id:2,
status: "active",
dataDetail: {
id: 8,
name: tes 2,
region: bbb,
}
},
{id:3,
status: "active",
dataDetail: {
id: 8,
name: tes 3,
region: aaa,
}
}
]
==> Two JSON
aaa: [
{id:1,
status: "active",
dataDetail: {
id: 5,
name: tes 1,
region: aaa,
}
},
{id:3,
status: "active",
dataDetail: {
id: 8,
name: tes 3,
region: aaa,
}
}
],
bbb: [
{id:2,
status: "active",
dataDetail: {
id: 8,
name: tes 2,
region: bbb,
}
},
]
==> Result JSON
aaa:
1
3
bbb:
2
thanks
Using Lodash:
const jsonTwo = _.groupBy(data, instance => instance.dataDetail.region);
const resultJson = _.mapValues(jsonTwo, regionInstances => regionInstances.map(instance => instance.id));
Using plain javascript reduce functions:
const jsonTwo = data.reduce((accumulator, instance) => {
if(!accumulator[instance.dataDetail.region]) {
accumulator[instance.dataDetail.region] = [];
}
accumulator[instance.dataDetail.region].push(instance)
return accumulator;
},{});
const resultJson = data.reduce((accumulator, instance) => {
if(!accumulator[instance.dataDetail.region]) {
accumulator[instance.dataDetail.region] = [];
}
accumulator[instance.dataDetail.region].push(instance.id)
return accumulator;
},{});
var data =
[
{
"id": 1,
"status": "active",
"dataDetail": {
"id": 5,
"name": "tes 1",
"region": "aaa"
}
},
{
"id": 2,
"status": "active",
"dataDetail": {
"id": 8,
"name": "tes 2",
"region": "bbb"
}
},
{
"id": 3,
"status": "active",
"dataDetail": {
"id": 8,
"name": "tes 3",
"region": "aaa"
}
}
];
groups =_.chain(data).groupBy('dataDetail.region');
keys = groups.map( (value, key) => key);
values = groups.map( (value, key) => _.map(value, 'id'));
result = _.zipObject(keys, values);
I want to create a treeview array for use in Angular UI Tree. I want to create the structure from a array of object like this:
0: Object
body: null
categoryDescription: null
categoryTopic: null
description: null
faqBodyId: 0
faqCategoryId: 0
faqGroupId: 1
groupDescription: null
groupName: "Generelt"
groupTopic: "Generelt"
themeCode: "GEN"
topic: null
1: Object body: null categoryDescription: "Test af kategori" categoryTopic: "Mail" description: null faqBodyId: 0 faqCategoryId: 2 faqGroupId: 1 groupDescription: null groupName: null groupTopic: null themeCode: null topic: null
2: Object body: "This is a test" categoryDescription: null categoryTopic: null description: "Testing" faqBodyId: 3 faqCategoryId: 2 faqGroupId: 0 groupDescription: null groupName: null groupTopic: null themeCode: null topic: "Test123"
etc...
It is in three levels. Group, Category and Body
A node does not allways have a child!
I want It in this structure and three levels:
[
{
"id": 1,
"title": "1. dragon-breath",
"items": []
},
{
"id": 2,
"title": "2. moiré-vision",
"items": [
{
"id": 21,
"title": "2.1. tofu-animation",
"items": [
{
"id": 211,
"title": "2.1.1. spooky-giraffe",
"items": []
},
{
"id": 212,
"title": "2.1.2. bubble-burst",
"items": []
}
]
},
{
"id": 22,
"title": "2.2. barehand-atomsplitting",
"items": []
}
]
},
{
"id": 3,
"title": "3. unicorn-zapper",
"items": []
},
{
"id": 4,
"title": "4. romantic-transclusion",
"items": []
}
]
Structure
How is that done with Angular code?
I solved the problem like this.
The input array is sorted:
function buildtree(arr) {
var group = [];
angular.forEach(arr, function (value, index) {
if (value.faqGroupId > 0 && value.faqCategoryId == 0 && value.faqBodyId == 0) {
var category = [];
var faqgroup = {
"id": value.faqGroupId,
"title": value.groupTopic,
"description": value.groupDescription,
"name": value.groupName,
"items": category
}
angular.forEach(arr, function (valuecat, index) {
if (value.faqGroupId == valuecat.faqGroupId && valuecat.faqCategoryId > 0 && valuecat.faqBodyId == 0) {
var body = [];
var faqcat = {
"id": valuecat.faqCategoryId,
"title": valuecat.categoryTopic,
"description": valuecat.categoryDescription,
"items": body
}
angular.forEach(arr, function (valuebod, index) {
if (valuecat.faqGroupId == valuebod.faqGroupId && valuecat.faqCategoryId == valuebod.faqCategoryId && valuebod.faqBodyId > 0) {
var faqbody = {
"id": valuebod.faqBodyId,
"title": valuebod.topic,
"description": valuebod.description,
"body": valuebod.body,
}
body.push(faqbody);
}
})
category.push(faqcat);
}
})
group.push(faqgroup);
}
});
return group;
}
Array list :
Flat object array list
var dataList= [
{'id':1 ,'parentid' : 0, 'label'="label 1"},
{'id':4 ,'parentid' : 2 ,'label'="label 2"},
{'id':3 ,'parentid' : 1, 'label'="label 3"},
{'id':5 ,'parentid' : 0, 'label'="label 4"},
{'id':6 ,'parentid' : 0, 'label'="label 5"},
{'id':2 ,'parentid' : 1, 'label'="label 6"},
{'id':7 ,'parentid' : 4, 'label'="label 7"},
{'id':8 ,'parentid' : 1, 'label'="label 8"}
];
covert flat object array list to treeview list
function flatListToTreeViewData(dataList) {
var tree = [],
mappedArr = {},
arrElem,
mappedElem;
for (var i = 0, len = dataList.length; i < len; i++) {
arrElem = dataList[i];
mappedArr[arrElem.id] = arrElem;
mappedArr[arrElem.id]['children'] = [];
}
for (var id in mappedArr) {
if (mappedArr.hasOwnProperty(id)) {
mappedElem = mappedArr[id];
array of children.
if (mappedElem.parentID) {
mappedArr[mappedElem['parentID']]['children'].push(mappedElem);
}else {
tree.push(mappedElem);
}
}
}
return tree;
}