How to loop array after process groupBy in React-Native - reactjs

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);

Related

Mongodb update nested array by key-value

How can I update nested array by list key value?
{
"_id": "mainId",
"events": [{
"id": 1,
"profile": 10,
} {
"id": 2,
"profile": 10,
} {
"id": 3,
"profile": 20,
}
]
}
and I have a list to update:
var list = {id: 2, newval: 222}, {id: 3, newval: 333}
How can I do an update in one query? Or in MongoDB, it will be like a loop?
for({id, val} in list){
update({_id: "mainId", events.$.id: id}, {setField: {events.$.profile: val}})
}
If you have a copy of the events array, you could make the necessary updates in your code and then send the updated array to MongoDB in a single query. Something like this
db.Test.updateOne({_id: "mainId"}, {$set: { "events": [{id: 1, profile: 222}, {id: 2, profile: 10}, {id: 3, profile: 333}] } } )
If you don't have a copy of the events array, you could do a bulk operation. Something like
db.Test.bulkWrite(
[
{ updateOne : {
"filter": {_id: "mainId", "events.id": 1},
"update": { $set: { "events.$.profile": 222 } }
}
},
{ updateOne : {
"filter": {_id: "mainId", "events.id": 3},
"update": { $set: { "events.$.profile": 333 }}
}
}
]
)
For more on bulkWrite, see the MongoDB docs: https://docs.mongodb.com/manual/core/bulk-write-operations/#bulkwrite-methods

Massage JSON response to fit into treeData structure for react-simple-tree-menu

I have a React component that retrieves an array of objects (key-value pairs) from a REST API via an HTML endpoint:
[
{
"id": 1,
"grouping1": "first-level-node-1",
"grouping2": "second-level-node-1",
"theThing": "third-level-node-1",
"someData": "data here that is associated with theThing",
"someUrl": "http://someurl.com"
},
{
"id": 2,
"grouping1": "first-level-node-2",
"grouping2": "second-level-node-1",
"theThing": "third-level-node-1",
.
.
.
}
]
I am trying to manipulate the JSON response so that it gets displayed with react-simple-tree-menu. To generate a TreeMenu, data needs to be provided as an array:
// as an array
const treeData = [
{
key: 'first-level-node-1',
label: 'Node 1 at the first level',
..., // any other props you need, e.g. url
nodes: [
{
key: 'second-level-node-1',
label: 'Node 1 at the second level',
nodes: [
{
key: 'third-level-node-1',
label: 'Last node of the branch',
nodes: [] // you can remove the nodes property or leave it as an empty array
},
],
},
],
},
{
key: 'first-level-node-2',
label: 'Node 2 at the first level',
},
];
or as an object:
// or as an object
const treeData = {
'first-level-node-1': { // key
label: 'Node 1 at the first level',
index: 0, // decide the rendering order on the same level
..., // any other props you need, e.g. url
nodes: {
'second-level-node-1': {
label: 'Node 1 at the second level',
index: 0,
nodes: {
'third-level-node-1': {
label: 'Node 1 at the third level',
index: 0,
nodes: {} // you can remove the nodes property or leave it as an empty array
},
},
},
},
},
'first-level-node-2': {
label: 'Node 2 at the first level',
index: 1,
},
};
I have tried categorizing the JSON response based on grouping1 (first level node) and grouping2 (second level node) to make it 'fit' into the treeData:
const fetchItems = async () => {
const data = await fetch('http://localhost:3001/stuff');
const input = await data.json();
const output = input.reduce((acc, item) => ({
...acc,
[item.grouping1]: {
...acc[item.grouping1],
[item.grouping2]: [
...(acc[item.gropuing1] && acc[item.grouping1][item.grouping2] || []),
item,
]
}
}), {})
and now I have objects (grouping1) that contain objects (grouping2) that contain the array of key-value pairs.
first-level-node-1:
second-level-node-1: Array(4)
0: {id: 1, grouping1: "first-level-node-1", grouping2: "second-level-node-1", theThing: "third-level-node-1"}
.
.
.
first-level-node-2:
second-level-node-1: Array(16)
0: {id: 2, grouping1: "first-level-node-2", grouping2: "second-level-node-1", theThing: "third-level-node-1"}
.
.
.
But this isn't the treeData structure that react-simple-tree-menu wants. How can I massage the JSON response to fit the treeData structure?
Here's an excellent write-up for how to get a Sidebar Menu up and running in React, but nothing that shows how to get a typical JSON response to fit into the required structure.
Update:
The following is the TreeMenu data that controls this react-simple-tree-menu component
<TreeMenu
data={[
{
key: 'mammal',
label: 'Mammal',
nodes: [
{
key: 'canidae',
label: 'Canidae',
nodes: [
{
key: 'dog',
label: 'Dog',
nodes: [],
url: 'https://www.google.com/search?q=dog'
},
{
key: 'fox',
label: 'Fox',
nodes: [],
url: 'https://www.google.com/search?q=fox'
},
{
key: 'wolf',
label: 'Wolf',
nodes: [],
url: 'https://www.google.com/search?q=wolf'
}
],
url: 'https://www.google.com/search?q=canidae'
}
],
url: 'https://www.google.com/search?q=mammal'
},
{
key: 'reptile',
label: 'Reptile',
nodes: [
{
key: 'squamata',
label: 'Squamata',
nodes: [
{
key: 'lizard',
label: 'Lizard',
url: 'https://www.google.com/search?q=lizard'
},
{
key: 'snake',
label: 'Snake',
url: 'https://www.google.com/search?q=snake'
},
{
key: 'gekko',
label: 'Gekko',
url: 'https://www.google.com/search?q=gekko'
}
],
url: 'https://www.google.com/search?q=squamata'
}
],
url: 'https://www.google.com/search?q=reptile'
}
]}
debounceTime={125}
disableKeyboard={false}
hasSearch
onClickItem={function noRefCheck(){}}
resetOpenNodesOnDataUpdate={false}
/>
If I'm understanding this correctly, Mammal is first-level-node-1 and Reptile is first-level-node-2. Canidae and Squamata are both second-level-node-1 under their respective first-level-nodes. Dog, Fox and Wolf are third-level-node-1, node-2 and node-3 respectively. Lizard, Snake and Gekko are also third-level-node-1, node-2 and node-3. The example I used at the very top of this post may be confusing things. My apologies if that is the case.
Here is the JSON data that more closely resembles what I'm working with:
[
{
"id": 2,
"grouping1": "I124",
"grouping2": "Cross_Streets",
"theThing": "12th",
"url": "http://url2.com"
},
{
"id": 3,
"grouping1": "I124",
"grouping2": "Cross_Streets",
"theThing": "13th",
"url": "http://url3.com"
},
{
"id": 4,
"grouping1": "I124",
"grouping2": "Cross_Streets",
"theThing": "4th",
"url": "http://url4.com"
},
{
"id": 14,
"grouping1": "I124",
"grouping2": "Ramps",
"theThing": "Ramp_A",
"url": "http://url14.com"
},
{
"id": 15,
"grouping1": "I124",
"grouping2": "Ramps",
"theThing": "Ramp_B",
"url": "http://url15.com"
},
{
"id": 41,
"grouping1": "I75",
"grouping2": "Cross_Streets",
"theThing": "100th",
"url": "http://url41.com"
}
]
The goal is to make the above JSON look like this in react-simple-tree-menu:
+ I124
+ Cross_Streets
12th
13th
4th
+ Ramps
Ramp_A
Ramp_B
+ I75
+ Cross_Streets
4th
Here's a possible solution that you could apply, however, I am not sure where you are getting the labels from, but I'll leave that up to you.
Here's an example with an object as the result:
const DATA = [
{
id: 2,
grouping1: "I124",
grouping2: "Cross_Streets",
theThing: "12th",
url: "http://url2.com"
},
{
id: 3,
grouping1: "I124",
grouping2: "Cross_Streets",
theThing: "13th",
url: "http://url3.com"
},
{
id: 4,
grouping1: "I124",
grouping2: "Cross_Streets",
theThing: "4th",
url: "http://url4.com"
},
{
id: 14,
grouping1: "I124",
grouping2: "Ramps",
theThing: "Ramp_A",
url: "http://url14.com"
},
{
id: 15,
grouping1: "I124",
grouping2: "Ramps",
theThing: "Ramp_B",
url: "http://url15.com"
},
{
id: 41,
grouping1: "I75",
grouping2: "Cross_Streets",
theThing: "100th",
url: "http://url41.com"
}
];
const resultAsObject = DATA.reduce((accumulator, item) => {
const groupId = item["grouping1"];
const subGroupId = item["grouping2"];
const subGroupItemId = item["theThing"];
const url = item["url"];
const group = accumulator[groupId] || {
key: groupId.toLowerCase(),
label: groupId,
nodes: []
};
const subGroup = group.nodes.find(
item => item.key === subGroupId.toLowerCase()
) || {
key: subGroupId.toLowerCase(),
label: subGroupId,
nodes: []
};
const updatedSubGroupNodes = [
{
key: subGroupItemId.toLowerCase(),
label: subGroupItemId,
url: url,
nodes: []
}
];
const updatedSubGroup = {
...subGroup,
nodes: updatedSubGroupNodes
};
const t1 = [...group.nodes, updatedSubGroup].reduce((acc, i) => {
const category = acc.find(t => t.key === i.key) || {
key: i.key,
label: i.label,
nodes: []
};
const updatedNodes = [...category.nodes, ...i.nodes];
const updatedCategory = { ...category, nodes: updatedNodes };
// replace the existing category object and append
// the updated object with populated `nodes` property
return [...acc.filter(t => t.key !== category.key), updatedCategory];
}, []);
const updatedGroup = {
...group,
nodes: t1
};
return {
...accumulator,
[groupId]: updatedGroup
};
}, {});
console.log(resultAsObject);

Issues with transforming array data

I'm trying to transform the following JSON array data structure -
From
[
{
"date": "2019-01-01",
"marks": [
{
"quantity": {
"shoes": 1,
"belt": 2,
"socks": 3
}
}
]
},
{
"date": "2019-01-02",
"marks": [
{
"quantity": {
"shoes": 4,
"belt": 5,
"socks": 6
}
}
]
}
]
To
rows: [
{
values: [ '2019-01-01', 1, 2, 3]
},
{
values: [ '2019-01-02', 4, 5, 6]
}
]
The code that I was able to try so far is this -
function myFunction() {
var response = [
{
"date": "2019-01-01",
"marks": [
{
"quantity": {
"shoes": 1,
"belt": 2,
"socks": 3
}
}
]
},
{
"date": "2019-01-02",
"marks": [
{
"quantity": {
"shoes": 4,
"belt": 5,
"socks": 6
}
}
]
}
];
var transform = response.map(function(dailyMarks) {
var row = [];
Object.keys(response).asArray().forEach(function (field) {
switch (field) {
case 'shoes':
return row.push(dailyMarks.shoes);
case 'belt':
return row.push(dailyMarks.belt);
case 'socks':
return row.push(dailyMarks.socks);
case 'date':
return row.push(dailyMarks.date);
default:
return row.push('');
}
});
return { values: row };
});
Logger.log(transform);
}
However, I'm running into this error -
TypeError: Cannot find function asArray in object 1,2. (line XX, file "Code")
Pretty sure I'm doing something wrong but have not been able to figure out where.
Objective is simply to transform the aforementioned data structure - approach doesn't really matter.
Any help would be highly appreciated! Thanks.
In ES5,
var arr1 = [
{
date: '2019-01-01',
marks: [
{
quantity: {
shoes: 1,
belt: 2,
socks: 3,
},
},
],
},
{
date: '2019-01-02',
marks: [
{
quantity: {
shoes: 4,
belt: 5,
socks: 6,
},
},
],
},
];
var out = [];
arr1.forEach(function(obj) {
obj.marks.forEach(function(mark) {
out.push({
values: [obj.date].concat(
Object.keys(mark.quantity).map(function(key) {
return mark.quantity[key];
})
),
});
});
});
console.log({ rows: out });
You could take an array of keys for the order and flatmap the marks array.
var data = [{ date: "2019-01-01", marks: [{ quantity: { shoes: 1, belt: 2, socks: 3 } }] }, { date: "2019-01-02", marks: [{ quantity: { shoes: 4, belt: 5, socks: 6 } }] }],
keys = ['shoes', 'belt', 'socks'],
rows = data.map(({ date, marks }) =>
({ values: [date, ...marks.flatMap(({ quantity }) => keys.map(k => quantity[k]))] })),
result = { rows };
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
let x = products.map(p=>{
return p.marks.reduce((t,m)=>{
t.push({ values: [p.date, ...Object.entries(m.quantity).map(([key, value]) => value)]})
return t;
},[])
}
).flat(2)
console.log(x)
var list=[{"date":"2019-01-01","marks":[{"quantity":{"shoes":1,"belt":2,"socks":3}}]},{"date":"2019-01-02","marks":[{"quantity":{"shoes":4,"belt":5,"socks":6}}]}];
let result = list.map(( {date, marks} ) => { return {value: [date, ...Object.values(marks[0].quantity)]};});
let wrap = {rows: result};
console.log(wrap);

How to normalize paginated data?

I need to convert a data like this:
{peopleList: [{id:1, name: 'joe'}, {id: 2, name: 'john'}], page: 1, rowPerPage: 8}
to this model:
{entities: {'0': {id: 0, name: 'joe'}, '1': {id: 1, name: 'john'}, page: 1, rowPerPage: 8}, result: [0, 1]}
but when I add this schema:
const people = new schema.Entity('peopleList');
const normalizedData = normalize(_data, { peopleList: [people] });
I get this output:
{
"entities": {
"peopleList": {
"1": {
"id": 1,
"name": "joe"
},
"2": {
"id": 2,
"name": "john"
}
}
},
"result": {
"peopleList": [
1,
2
],
"page": 1,
"rowPerPage": 8
}
}
I don't know exactly how to make a proper schema that create result filed as my desire. maybe the correct way is to have it in result and this output is correct. any idea?

Combining Column charts and line charts with the same same data in the same container(Highcharts)

I want to build a combination chart with a column chart with multiple series and a line chart. Problem is that I am getting High charts data from nested JSON response. For that I initialized array and that array is giving in series in plotoptions highcharts as you can see in the below code.
My code is like this:
var crime_data=[];
for(var i=0;i<result.themes.length;i++){
var crime={};
var test2 = result.themes[i];
var test = test2[Object.keys(test2)];
crime.name = Object.keys(result.themes[i]);
crime.data = [];
for(var k=0;k<test.yearTheme.length;k++){
var test3=test.yearTheme[k];
var test5=test3.individualValueVariable;
for(var j=0;j<test5.length;j++){
crime.data.push(test5[j].count);
};
};
crime_data.push(crime);
};
var crimeChart = new Highcharts.Chart({
chart: {
renderTo: 'container1',
type:'column'
},
title: {
text: 'Crime'
},
xAxis: {
categories: month,
crosshair: true
},
yAxis: {
min: 0,
title: {
text: 'Count'
}
},
credits: {
enabled: false
},
tooltip: {
shared: true,
},
plotOptions: {
column: {
pointPadding: 0.2,
borderWidth: 0,
depth: 25,
allowPointSelect: true,
cursor: 'pointer',
point: {
},
}
},
series: crime_data
});
This is Column chart I am getting when i write chart type column.
This is my Line Chart I am getting when i changed type column to spline in chart in highcharts.
And this is my JSON data(Highcharts data):
{
"boundaries": {
"boundary": [
{
"boundaryId": "55083021003",
"boundaryType": "USA_CITY",
"boundaryRef": "C1"
}
]
},
"themes": [
{
"AssaultCrimeTheme": {
"boundaryRef": "C1",
"individualValueVariable": [
{
"name": "2013 Assault Crime",
"description": "Assault Crime for 2013",
"count": 18901
},
{
"name": "2014 Assault Crime",
"description": "Assault Crime for 2014",
"count": 17707
}
]
}
},
{
"BurglaryCrimeTheme": {
"boundaryRef": "C1",
"individualValueVariable": [
{
"name": "2013 Burglary Crime",
"description": "Burglary Crime for 2013",
"count": 17743
},
{
"name": "2014 Burglary Crime",
"description": "Burglary Crime for 2014",
"count": 14242
}
]
}
}
]
}
I want to combine both of them in the same container with same data.The problem is in how to tell highcharts multiple series should be represented with line and with column type with same data.For this when i write series:[{ data: crime_data ,type: spline }] instead of series:crime_data In that case I am not getting Highcharts data. Can anyone Please help me how should i do this.Please suggest me.
Pass your data, like below format. add type of chart in each data series;
Here i replaced type value but with same data.
[{
type: 'line',
name: 'AssaultCrimeTheme',
data: [3, 2, 1, 3, 4]
}, {
type: 'line',
name: 'BurglaryCrimeTheme',
data: [2, 3, 5, 7, 6]
}, {
type: 'column',
name: 'AssaultCrimeTheme',
data: [3, 2, 1, 3, 4]
}, {
type: 'column',
name: 'BurglaryCrimeTheme',
data: [2, 3, 5, 7, 6]
},]
Here is fiddle for more details.
Here is a complete example using your data.
const json = {
"boundaries": {
"boundary": [{
"boundaryId": "55083021003",
"boundaryType": "USA_CITY",
"boundaryRef": "C1"
}]
},
"themes": [{
"AssaultCrimeTheme": {
"boundaryRef": "C1",
"individualValueVariable": [{
"name": "2013 Assault Crime",
"description": "Assault Crime for 2013",
"count": 18901
}, {
"name": "2014 Assault Crime",
"description": "Assault Crime for 2014",
"count": 17707
}]
}
}, {
"BurglaryCrimeTheme": {
"boundaryRef": "C1",
"individualValueVariable": [{
"name": "2013 Burglary Crime",
"description": "Burglary Crime for 2013",
"count": 17743
}, {
"name": "2014 Burglary Crime",
"description": "Burglary Crime for 2014",
"count": 14242
}]
}
}]
}
// Create categories object in order filter duplicates
const cats = {}
const series = json.themes.map((o) => {
const key = Object.keys(o)[0]
return {
name: key,
data: o[key].individualValueVariable.map((o) => {
cats[o.name] = 1
return { category: o.name, y: o.count }
})
}
})
// Convert categories object to array
const categories = Object.keys(cats)
// Chart options
const options = {
chart: {type: 'column'},
xAxis: {categories: categories},
series: series
}
// Create chart
const chart = Highcharts.chart('container', options)
console.log(series, categories)
Live example: https://jsfiddle.net/Lo323gq3/
Output below:

Resources