I need to transform below Json array to another array as mentioned below using angularjs/ javascript.
Input Array = [{"Name":"123", "Type": "Type1", "Total":"24"}, {"Name":"123", "Type": "Type2", "Total":"25"}, {"Name":"124", "Type": "Type1", "Total":"26"}, {"Name":"124", "Type": "Type2", "Total":"27"}]
Output Array: [{"Name":"123", "Type1":"24", "Type2":"25"}, {"Name":"124", "Type1":"26", "Type2":"27"}
I would work it out with reduce function I've added some comments for you inside as well:
let inputArray = [{"Name":"123", "Type": "Type1", "Total":"24"}, {"Name":"123", "Type": "Type2", "Total":"25"}, {"Name":"124", "Type": "Type1", "Total":"26"}, {"Name":"124", "Type": "Type2", "Total":"27"}];
// and do reduce function on it
inputArray.reduce((prevVal, currVal, index) => {
// first check if there's Name in already
if (prevVal.find(x => x.Name === currVal.Name)) {
// if there's a Name same as current element use new type as a key and add Total
prevVal.find(x => x.Name === currVal.Name)[currVal.Type] = currVal.Total;
} else {
// in case there's no Name then just create object with it
prevVal.push({
Name: currVal.Name,
[currVal.Type]: currVal.Total
});
}
return prevVal;
}, []);
Here's fiddle:
https://jsfiddle.net/pegla/s9hwbth4/
All you have to do is, get the unique objects from the original list based on Name.
var obj = [{
"Name": "123",
"Type": "Type1",
"Total": "24"
},
{
"Name": "123",
"Type": "Type2",
"Total": "25"
},
{
"Name": "124",
"Type": "Type1",
"Total": "26"
},
{
"Name": "124",
"Type": "Type2",
"Total": "27"
}
];
var getIndex = function(list, property, object) {
for (var i = 0; i < list.length; i++) {
if (list[i][property] == object[property]) {
return i;
}
}
return -1;
}
var result = [];
for (var i = 0; i < obj.length; i++) {
/* Call getIndex to return the index of element in the result and add the type name property */
var index = getIndex(result, 'Name', obj[i]);
if (index != -1) {
result[index][obj[i].Type] = obj[i].Total;
} else {
var newObj = {};
newObj.Name = obj[i].Name;
newObj[obj[i].Type] = obj[i].Total;
result.push(newObj);
}
}
console.log(result);
You don't need angularjs to do that. You can do that using simple javascript for block. Please see attached code. Best,
let input = [{"Name":"123", "Type": "Type1", "Total":"24"}, {"Name":"123", "Type": "Type2", "Total":"25"}, {"Name":"124", "Type": "Type1", "Total":"26"}, {"Name":"124", "Type": "Type2", "Total":"27"}];
let output = [];
for(let i=0; i<input.length-1;i++){
output.push({
"Name":input[i].Name,
"Type1":input[i].Total,
"Type2":input[i+1].Total,
});
i++;
}
console.log(output);
Related
I have an array of objects with the following format
var arr = [
{
"productId": "123456",
"productName": "Test Product 1",
"description": [
"This is delicious",
"Suitable for vegetarian"
],
"attributes": {
"internalId": "091283"
"category": "Dairy"
},
"order": 1
}
];
And I am trying to map into something like below
[
[{
{
"name": "productId",
"value": "123456"
},
{
"name": "productName",
"value": "Test Product 1"
},
{
"name": "description",
"value": ["This is delicious", "Suitable for vegetarian"]
},
{
"name": "attributes",
"value": {
{
"name": "internalId",
"value": "091283"
},
{
"name": "category",
"value": "Dairy"
}
}
},
{
"name": "order",
"value": 1
}
}]
]
I tried mapping simple properties before going further and now stuck at getting only the last property of each object in the loop.
Suppose I don't know what are the format of incoming data and how can I normalize the JSON object to the format I want?
normalizeJson = (array) => {
for(i = 0; i < array.length; i++){
normalizedJson[i] = {};
Object.keys(array[i]).forEach(key => {
if (array[i][key] && typeof array[i][key] === "object") {
// normalizeJson(obj[key]);
// console.log(key + ' is object');
return;
} else {
o = {};
o["name"] = key;
o["value"] = array[i][key];
normalizedJson[i] = o;
// normalizedJson[i]["name"] = key;
// normalizedJson[i].value = array[i][key];
// console.log(key);
return;
}
});
}
console.log(normalizedJson);
};
Or is there any library I can use in order to achieve this?
Try this
var obj = [
{
productId: "123456",
productName: "Test Product 1",
description: ["This is delicious", "Suitable for vegetarian"],
attributes: {
internalId: "091283",
category: "Dairy",
},
order: 1,
},
];
function normalizeObject(obj) {
var result = [];
if (Array.isArray(obj)) {
for (let i of obj) {
result.push(normalizeObject(i));
}
} else if (typeof obj == "object") {
for (let i of Object.keys(obj)) {
result.push({ name: i, value: normalizeObject(obj[i]) });
}
} else {
return obj;
}
return result;
}
console.log(JSON.stringify(normalizeObject(obj), null, 2));
This looping method called recursion. Which is loop by calling function itself.
I'm struggling with the following issue:
I have a nested object. From the server I get a response with an object with changed values. So I want to find the object in my nested object and replace it.
My object has a structure like this:
$scope.page = {
id: 5,
label: 'myPage',
items : [
{
"type": "Container",
"id": 1,
"label": "header",
"items": [
{
"type": "Container",
"id": 2,
"label": "left",
"items": [
{
"type": "Menu",
"label": "settings-menu",
"id": "5"
},
{
"type": "Menu",
"label": "main-menu",
"id": "7"
}
]
},
{
"type": "Container",
"id": 4,
"label": "right",
"items": [
{
"type": "Post",
"label": "contact",
"id": "25"
}
]
}
]
},
{
"type": "Postlist",
"label": "nieuwsberichten",
"id": "17"
},
{
"type": "HTML",
"label": "over deze site",
"id": "18"
},
{
"type": "Other",
"label": "twitter feed",
"id": "19"
}
]
}
From the server I get a new object:
var newItem = {
"type": "Post",
"label": "contact",
"id": "25"
}
How can I update the object inside $scope.page the right way? I've tried the following:
$scope.findAndReplace(newItem,$scope.page.items);
$scope.findAndReplace = function(newItem, items) {
for (var i = 0; i < items.length; i++) {
if (items[i].id == newItem.id) {
items[i] = newItem;
} else if (items[i].items) {
$scope.findAndReplace(newItem, items[i].items);
}
}
}
and:
var oldItem = $scope.findById(item.id, $scope.page.items);
oldItem = newItem;
$scope.findById = function(id, items) {
var match = null;
angular.forEach(items, function(i){
if (match == null) {
if (i.id == id) {
match = i;
} else if (i.items) {
match = $scope.findById(id, i.items)
}
}
})
return match;
}
Neither of these options work. That's because of the nested loops where the object isn't the one in $scope.page anymore.
Anyone an idea to handle this?
Your example looks fine, can't understand why they are not working.
Neither of these options work. That's because of the nested loops where the object isn't the one in $scope.page anymore.
You can keep object reference by using angular.copy(newItem, oldItem)
Hi I have created a fiddle for you.
click for fiddle
for(var indx=0; indx < $scope.page.items.length; indx++) {
var tmpObj = $scope.page.items[indx];
if(tmpObj.hasOwnProperty('items')) {
// check inside
for(var indx1=0; indx1<tmpObj.items.length; indx1++ ) {
var innerObj = tmpObj.items[indx1];
// check for next level
if(innerObj.hasOwnProperty('items')) {
for(var counter=0; counter< innerObj.items.length; counter++) {
var thirdTmp = innerObj.items[counter];
console.log('3rd level inner object', thirdTmp);
if(thirdTmp.id === newItem.id) {
innerObj.items[counter] = newItem;
tmpObj.items[indx1] = innerObj;
$scope.page.items[indx] = tmpObj;
}
}
}
}
} else if(tmpObj.id === newItem.id) {
$scope.page.items[indx] = newItem;
}
};
I have this array that needs to be parsed into a useful object. The names of each value are a collection of namespaces separated by / characters. The values between each '/' need to be turned into a JS Objects property:
"status": [
{
"message": "OK",
"name": "/Computer",
"values": []
},
{
"name": "/Computer/CPU Usage",
"values": []
},
{
"name": "/Computer/CPU Temp",
"values": []
},
{
"name": "/Computer/hardware/memory",
"values": []
}
]
I need it to become this:
"status": {
"computer": {
"CPU Usage": {
"values": []
},
"CPU Temp": {
"values": []
},
"hardware": {
"memory": {
"values": []
}
}
}
}
So far I have done this:
var statii = status, // from above..
_parsedStatii = {};
for (var i = 0; statii.length < 0; i ++) {
var _nameSpaces = statii[i].name.split('/');
// Start at 1 because index 0 is empty (before the first slash)
if (!_parsedStatii[_nameSpaces[1]]) {
_parsedStatii[_nameSpaces[1]] = {};
}
if (!_parsedStatii[_nameSpaces[1]][_nameSpaces[2]])
_parsedStatii[_nameSpaces[1]][_nameSpaces[2]] = {};
if (!_parsedStatii[_nameSpaces[1]][_nameSpaces[2]][_nameSpaces[3]])
_parsedStatii[_nameSpaces[1]][_nameSpaces[2]][_nameSpaces[3]] = {};
if (!_parsedStatii[_nameSpaces[1]][_nameSpaces[2]][_nameSpaces[3]][_nameSpaces[4]])
_parsedStatii[_nameSpaces[1]][_nameSpaces[2]][_nameSpaces[3]][_nameSpaces[4]] = {};
}
Obviously it is no where near right, I have tried a lot of recursive functions but am at a bit of a loss. This example gives the clearest representation of what I am trying to achieve. Any ideas? (Please excuse code typos, it was paraphrased)
You could split the name and build an object upon.
var data = { "status": [{ "message": "OK", "name": "/Computer", "values": [] }, { "name": "/Computer/CPU Usage", "values": [] }, { "name": "/Computer/CPU Temp", "values": [] }, { "name": "/Computer/hardware/memory", "values": [] }] },
object = {};
data.status.forEach(function (a) {
a.name.slice(1).split('/').reduce(function (o, k) {
return o[k] = o[k] || {};
}, object).values = a.values;
});
console.log(object);
.as-console-wrapper { max-height: 100% !important; top: 0; }
I have the following structure:
var struct = [{
"name": "Name1",
"type": "type1",
"children": [{
"name": "Name11",
"type": "type1",
"children": [{
"name": "Name111",
"type": "type1"
},
{
"name": "Name112",
"type": "type2"
}
}]
}]
}];
I want to iterate over all name-type elements where type is equal to type1 and create an <option> element for each one of them.
So it would be something like:
var iterate = function (data) {
var elements = [];
for (var i in data) {
if (data[i].type == 'type1') {
var option = document.createElement('option');
option.innerHTML = data[i].name;
elements.push(option);
elements.push(iterate(data[i].children));
}
}
return elements;
};
It however gives me wrong results. And probably is very inefficient. How should I do this properly?
You could use an iterative recursive approach for getting the nested data.
function getElements(data) {
var elements = [];
data.forEach(function iter(a) {
var option;
if (a.type === 'type1') {
option = document.createElement('option');
option.innerHTML = a.name;
elements.push(option);
Array.isArray(a.children) && a.children.forEach(iter); // assuming only
} // type1 branches
}); // to iterate
return elements;
}
var struct = [{ "name": "Name1", "type": "type1", "children": [{ "name": "Name11", "type": "type1", "children": [{ "name": "Name111", "type": "type1" }, { "name": "Name112", "type": "type2" }] }] }];
console.log(getElements(struct));
I think that you must not use any "element" var, just try this:
var iterate = function (data) {
for (var i in data) {
if (data[i].type == 'type1') {
var option = document.createElement('option');
option.innerHTML = data[i].name;
data[i].push(option);
iterate(data[i].children);
}
}
return data;
};
I have following array:
var array = [
{
"milestoneTemplate": {
"id": "1",
"name": "TEST1"
},
"id": "1",
"date": "1416680824",
"type": "ETA",
"note": "Note",
"color": "66FF33"
},
{
"milestoneTemplate": {
"id": "2",
"name": "Test 2"
},
"id": "2",
"date": "1416680824",
"type": "ATA",
"note": "Note 22",
"color": "66FF00"
}
];
And now i would like to check in forEach loop that object (which is passed in param of the function) is existing in array by his ID.
In case that not = do push into existing array.
arrayOfResults.forEach(function(entry) {
if(entry != existingInArrayByHisId) {
array.push(entry);
}
});
Thanks for any advice
You could create a helper function thats checks if an array contains an item with a matching property value, something like this:
function checkForMatch(array, propertyToMatch, valueToMatch){
for(var i = 0; i < array.length; i++){
if(array[i][propertyToMatch] == valueToMatch)
return true;
}
return false;
}
which you can then use like so:
arrayOfResults.forEach(function (entry) {
if (!checkForMatch(array, "id", entry.id)) {
array.push(entry);
}
});