I have an array as under
Data =
[
{
"field": "Classifications.LEV_2_HIER_NME",
"value": "Treasury Note",
"aggregates": {
"VALVAL_ALT_CMB_AMT": {
"sum": "5,981,210,920.0000"
}
},
"Items": [
{
"field": "Classifications.LEV_1_HIER_NME",
"value": "Treasury 1",
"aggregates": {
"VALVAL_ALT_CMB_AMT": {
"sum": "5,981,210,920.0000"
}
},
"Items": []
},
{
"field": "Classifications.LEV_1_HIER_NME",
"value": "Treasure 1",
"aggregates": {
"VALVAL_ALT_CMB_AMT": {
"sum": "5,981,210,920.0000"
}
},
"Items": []
}
]
},
{
"field": "Classifications.LEV_2_HIER_NME",
"value": "Treasury Note",
"aggregates": {
"VALVAL_ALT_CMB_AMT": {
"sum": "8,981,210,920.0000"
}
},
"Items": [
{
"field": "Classifications.LEV_1_HIER_NME",
"value": "Treasury 1",
"aggregates": {
"VALVAL_ALT_CMB_AMT": {
"sum": "8,981,210,920.0000"
}
},
"Items": []
},
{
"field": "Classifications.LEV_1_HIER_NME",
"value": "Treasure 1",
"aggregates": {
"VALVAL_ALT_CMB_AMT": {
"sum": "8,981,210,920.0000"
}
},
"Items": []
}
]
}
]
Data array has two objects. I want to merge the aggregate property of second object in the first one.
something like this:
[
{
"field": "Classifications.LEV_2_HIER_NME",
"value": "Treasury Note",
"aggregates": {
"VALVAL_ALT_CMB_AMT": {
"sum": "5,981,210,920.0000"
},
"VALVAL_ALT_CMB_AMT_1": {
"sum": "8,981,210,920.0000"
}
},
"Items": [
{
"field": "Classifications.LEV_1_HIER_NME",
"value": "Treasury 1",
"aggregates": {
"VALVAL_ALT_CMB_AMT": {
"sum": "5,981,210,920.0000"
},
"VALVAL_ALT_CMB_AMT_1": {
"sum": "8,981,210,920.0000"
}
},
"Items": []
},
{
"field": "Classifications.LEV_1_HIER_NME",
"value": "Treasure 1",
"aggregates": {
"VALVAL_ALT_CMB_AMT": {
"sum": "5,981,210,920.0000"
},
"VALVAL_ALT_CMB_AMT_1": {
"sum": "8,981,210,920.0000"
}
},
"Items": []
}
]
}
]
is there any way to implement this. Level of nesting is dynamic but all the objects will have same structure.
To merge the 2 objects inside the array into 1, this involves
Step 1. extracting the required elements from the 2nd object
Step 2. adding it into the object of the first.
Suppose the array is read into a variable data, then this is 1 way we can extract it in Step 1.
let {
aggregates: {
VALVAL_ALT_CMB_AMT
},
} = data[1];
The value paired to the VALVAL_ALT_CMB_AMT key of the 2nd object is stored inside a variable VALVAL_ALT_CMB_AMT. You can read more about Object Destructuring in Javascript.
For Step 2, we will add the value into the first variable. We can also think of objects to have similar syntax to maps, hence this is 1 way we can do it.
let first = data[0];
first["aggregates"]["VALVAL_ALT_CMB_AMT_1"] = VALVAL_ALT_CMB_AMT;
Extracting and adding the elements this way forms a shallow copy of the variable VALVAL_ALT_CMB_AMT, now as a value of VALVAL_ALT_CMB_AMT_1. Consequently, it is not advisable to delete the actual object in position 1 from the original array. Instead, it might be better to return the new object first in a new array.
const result = [first];
return result;
Related
Trying to get my head around this one..
Incoming data looks like:
[
{
"value": {
"label": "MZ Algal bloom",
"type": "case",
"incident": {
"name": "Algal bloom"
},
"personName": "Lionel Carter"
}
},
{
"value": {
"label": "BW Algal bloom",
"type": "case",
"incident": {
"name": "Algal bloom"
},
"personName": "Jerome Yost"
}
},
{
"value": {
"label": "Detergent",
"type": "case",
"incident": null,
"personName": "Jerald Legros"
}
}
]
I would like to transform this into
[
{
"label": "Algal bloom",
"children": [
{ "label": "Lionel Carter", "type": "case"},
{ "label": "Jerome Yost", "type": "case" }]
},
{ "label": "Detergent", "type": "case" }
]
Basically, the rule is that if incident is not NULL then the incident name becomes the parent and the children hold the personName - otherwise we simply pass through the label and type. I can walk the array and switch out the label with the incident name, but I'm not sure how to group up the incidents..
It's basic grouping with an exception for elements without incident.
You can group the elements without incident in a separate group:
const data = [{"value": {"label": "MZ Algal bloom","type": "case","incident": {"name": "Algal bloom"},"personName": "Lionel Carter"}},{"value": {"label": "BW Algal bloom","type": "case","incident": {"name": "Algal bloom"},"personName": "Jerome Yost"}},{"value": {"label": "Detergent","type": "case","incident": null,"personName": "Jerald Legros"}}];
function group(data) {
const result = data.reduce((acc, { value }) => {
if (!value.incident) {
acc.ungrouped.push({ label: value.label, type: value.type });
} else {
if (!acc.groups[value.incident.name]) acc.groups[value.incident.name] = { label: value.incident.name, children: [] };
acc.groups[value.incident.name].children.push({ label: value.personName, type: value.type });
}
return acc;
}, { groups: {}, ungrouped: [] });
return [...Object.values(result.groups), ...result.ungrouped];
}
console.log(group(data));
In my case i have a 2 db queries which are objects, one which returns all possible items which consists of a key and name field and then the other is a object which has the key, name and value field. What i am trying to do is to merge both objects where object 1 is the main object and object 2 should be merged into it.
What i ideally want is to return all items in Data2 with the value field merged into data2 and 0 if there is no data in data 1. if thats not possible i would be ok with no value in items in data 2 but i get even a strange result for that.
Fyi i am using underscore
const data1 = [
{
"count": 2,
"key": "c28f7ead-d87b-4ad5-b6b3-1f204b013b50",
"name": "Notes Written"
},
{
"count": 1,
"key": "d0181c74-22a9-4f99-9cc9-df3467c51805",
"name": "Pop-Bys Delivered"
},
{
"count": 2,
"key": "90d142ea-6748-4781-b2b9-4f05aab12956",
"name": "Database Additions"
},
{
"count": 1,
"key": "723e95dd-8c47-48ed-b9c3-1b010b092a1b",
"name": "Referals Given"
}
]
const data2 = [
{
"key": "8646ec5d-7a72-49bd-9a68-cf326d1c4a14",
"name": "Calls Made"
},
{
"key": "c28f7ead-d87b-4ad5-b6b3-1f204b013b50",
"name": "Notes Written"
},
{
"key": "d0181c74-22a9-4f99-9cc9-df3467c51805",
"name": "Pop-Bys Delivered"
},
{
"key": "90d142ea-6748-4781-b2b9-4f05aab12956",
"name": "Database Additions"
},
{
"key": "723e95dd-8c47-48ed-b9c3-1b010b092a1b",
"name": "Referals Given"
},
{
"key": "0f054686-ef13-4993-ac5b-f640ceeaaa8d",
"name": "Referals Received"
}
]
console.log(_.extend( data2, data1 ))
Here is a Replit example Sample Code
Using reduce, iterate over data1 while updating a Map of key-count pairs
Using each, iterate over data2 and set the value to the value of the key from the map, or 0 if it doesn't exist
const
data1 = [ { "count": 2, "key": "c28f7ead-d87b-4ad5-b6b3-1f204b013b50", "name": "Notes Written" }, { "count": 1, "key": "d0181c74-22a9-4f99-9cc9-df3467c51805", "name": "Pop-Bys Delivered" }, { "count": 2, "key": "90d142ea-6748-4781-b2b9-4f05aab12956", "name": "Database Additions" }, { "count": 1, "key": "723e95dd-8c47-48ed-b9c3-1b010b092a1b", "name": "Referals Given" } ],
data2 = [ { "key": "8646ec5d-7a72-49bd-9a68-cf326d1c4a14", "name": "Calls Made" }, { "key": "c28f7ead-d87b-4ad5-b6b3-1f204b013b50", "name": "Notes Written" }, { "key": "d0181c74-22a9-4f99-9cc9-df3467c51805", "name": "Pop-Bys Delivered" }, { "key": "90d142ea-6748-4781-b2b9-4f05aab12956", "name": "Database Additions" }, { "key": "723e95dd-8c47-48ed-b9c3-1b010b092a1b", "name": "Referals Given" }, { "key": "0f054686-ef13-4993-ac5b-f640ceeaaa8d", "name": "Referals Received" } ];
const map = _.reduce(
data1,
(map, { key, count }) => map.set(key, count),
new Map
);
_.each(
data2,
e => e.value = map.get(e.key) || 0
);
console.log(data2);
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.13.1/underscore-min.js" integrity="sha512-ZuOjyqq409+q6uc49UiBF3fTeyRyP8Qs0Jf/7FxH5LfhqBMzrR5cwbpDA4BgzSo884w6q/+oNdIeHenOqhISGw==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
The JSON provided is kind of unstructured and doesn't meet many of my
requirements. I have tried this many ways but does take a very long time
when I provide 100,000 records
Implemented Code
for (var f in stack.data) {
var field = new Object();
for (var o in stack.data[f]['field_values']) {
field[stack.data[f]['field_values'][o]['field_name']] = stack.data[f]['field_values'][o]['value'];
}
stack.data[f]['field_values'] = field;
}
console.log(JSON.stringify(stack, null, 2));
Input JSON:
var stack = {
"data": [{
"id": 950888888073,
"name": "www.stackoverflow.com",
"field_values": [{
"field_name": "Newsletter?",
"value": true
},
{
"field_name": "Parent",
"value": 950888661
},
{
"field_name": "Birthday",
"value": "2018-04-29"
},
{
"field_name": "Related matter",
"value": 1055396205
},
{
"field_name": "Referral",
"value": "Don Ho"
},
{
"field_name": "Spouse",
"value": "Wo Fat"
}
]
}]
}
Expected Output:
{
"data": [
{
"id": 950888888073,
"name": "www.stackoverflow.com",
"field_values": {
"Newsletter?": true,
"Parent": "Gigi Hallow",
"Birthday": "2018-04-29",
"Related": "2012-00121-Sass",
"Referral": "Don Ho",
"Spouse": "Wo Fat"
}
Sometimes "field_values can be empty. Need to check them as well
{
"id": 950821118875,
"name": "www.google.com",
"field_values": [],
}
This is mostly re-arranging the values. Here values becomes keys. There should actually be one liner to handle this, but i am run out of options.
Hope the question is clear
It would probably help to declare a variable to hold the array element, rather than doing 4 levels of indexing every time through the loop. You can also use destructuring to extract the properties of the object.
And use {} rather than new Object.
Even if this doesn't improve performance, it makes the code easier to read.
var stack = {
"data": [{
"id": 950888888073,
"name": "www.stackoverflow.com",
"field_values": [{
"field_name": "Newsletter?",
"value": true
},
{
"field_name": "Parent",
"value": 950888661
},
{
"field_name": "Birthday",
"value": "2018-04-29"
},
{
"field_name": "Related matter",
"value": 1055396205
},
{
"field_name": "Referral",
"value": "Don Ho"
},
{
"field_name": "Spouse",
"value": "Wo Fat"
}
]
}]
}
for (var f in stack.data) {
const field = {};
const fobj = stack.data[f];
for (var o in fobj.field_values) {
const {field_name, value} = fobj.field_values[o];
field[field_name] = value;
}
fobj.field_values = field;
}
console.log(JSON.stringify(stack, null, 2));
As an example - I've included a one element array that contains an object that has a Children key, which is an array of objects and each object also has its' own Children key that contains another array.
[
{
"Id": "1",
"Children": [
{
"Id": "2",
"Children": [
{
"Id": "10",
"DisplayName": "3-4",
},
{
"Id": "1000",
"DisplayName": "5-6",
},
{
"Id": "100",
"DisplayName": "1-2",
},
]
}
]
}
]
There is a second array of objects that I would like to compare the first array of objects to, with the intention of making sure that the first array is in the same order as the second array of objects, and if it is not - then sort until it is.
Here is the second array:
[
{
"Id": "1",
"Children": [
{
"Id": "2",
"Children": [
{
"Id": "100",
"DisplayName": "1-2",
},
{
"Id": "10",
"DisplayName": "3-4",
},
{
"Id": "1000",
"DisplayName": "5-6",
},
]
}
]
}
]
The data that this will run on can be up in the tens of thousands - so performance is paramount.
What I'm currently attempting is using a utility method to convert each element of the second array into a keyed object of objects e.g.
{
1: {
"Id": "1",
"Children": [
{
"Id": "2",
"Children": [
{
"Id": "4",
"DisplayName": "3-4",
},
{
"Id": "3",
"DisplayName": "1-2",
},
]
}
]
}
}
This allows fast look up from the top level. I'm wondering if I should continue doing this all the way down or if there is an idiomatic way to accomplish this. I considered recursion as well.
The order of the already sorted array is not based on Id - it is arbitrary. So the order needs to be preserved regardless.
Assuming same depth and all Id's exist in each level of each object use a recursive function that matches using Array#findIndex() in sort callback
function sortChildren(main, other) {
other.forEach((o, i) => {
if (o.children) {
const mChilds = main[i].children, oChilds = o.children;
oChilds.sort((a, b) => {
return mChilds.findIndex(main => main.Id === a.Id) - mChilds.findIndex(main => main.Id === b.Id)
});
// call function again on this level passing appropriate children arrays in
sortChildren(mChilds, oChilds)
}
})
}
sortChildren(data, newData);
console.log(JSON.stringify(newData, null, ' '))
<script>
var data = [{
"Id": "1",
"Children": [{
"Id": "2",
"Children": [{
"Id": "3",
"DisplayName": "1-2",
},
{
"Id": "4",
"DisplayName": "3-4",
},
]
}]
}]
var newData = [{
"Id": "1",
"Children": [{
"Id": "2",
"Children": [{
"Id": "4",
"DisplayName": "3-4",
},
{
"Id": "3",
"DisplayName": "1-2",
},
]
}]
}]
</script>
could you please help me to convert data in format like :
"tanks": [
{
"id": "1",
"name": {
"id": 1,
"tor": "000"
},
"type": {
"id": 1,
"system": "CV-001"
}
}
]
into
"tanks":[
{
"type": 1,
"name": 1
}
]
As you can see, type.id in the first array is the same as just type in the second. It is like I have to iterate through the array(as I have not only one Object in it) and left only needed fields in Objects, but I am stuck.
Hope it is a little informative for you.
You can do this with a simple Array.map()
var obj = {
tanks : [
{
"id": "1",
"name": {
"id": 1,
"tor": "000"
},
"type": {
"id": 1,
"system": "CV-001"
}
},
{
"id": "2",
"name": {
"id": 2,
"tor": "200"
},
"type": {
"id": 2,
"system": "CV-002"
}
}
]
};
obj.tanks = obj.tanks.map(function(item) {
return {
name : item.name.id,
type : item.type.id
};
});
console.log(obj);
<script src="http://gh-canon.github.io/stack-snippet-console/console.min.js"></script>