Move an object (element) one step up with Javascript - javascript

I have several objects like this:
I want to move type and value one step up so they will be next to field, and then delete data.
It looks like this when departments is converted to JSON:
[
{"field" : "DEPARTMAN_NO",
"data" : { "type":"numeric" , "comparison":"eq" , "value":11 }
},
{"field" : "DEPARTMAN_ADI",
"data" : { "type":"string" , "value":"bir" }
}
]
I have tried:
departments = grid.filters.getFilterData();
i = {};
for(var i in department) {
department = i.data;
delete.department.data;
};
but it dosen't work.

1) First, loop departments, each item we call it department;
2) You want to move department.data's properties to department, From another angle, you can move department's properties to department.data and return department.data, code like:
var departments = [{
"field": "DEPARTMAN_NO",
"data": {
"type": "numeric",
"comparison": "eq",
"value": 11
}
}, {
"field": "DEPARTMAN_ADI",
"data": {
"type": "string",
"value": "bir"
}
}],
department;
for (var i = 0, len = departments.length; i < len; i++) {
department = departments[i]; // department
for (var key in department) {
if (key !== 'data' && department.data) {
department.data[key] = department[key];
}
}
departments[i] = department.data || department; // if no department.data, no change
}
console.log(departments);
result:
view the full demo http://jsfiddle.net/KVYE5/

I wrote a little npm package that does what you're asking for: moving a property up a level in an object.
You can get it here: https://www.npmjs.com/package/move-property-up-a-level
Usage
var movePropertyUpALevel = require('movePropertyUpALevel');
var fakeObj = {
poodle: {
first: {
hey: 'you'
},
second: 'meAgain'
}
};
movePropertyUpALevel(fakeObj, 'poodle');
console.log(fakeObj.first.hey);
//'you'
console.log(fakeObj.poodle);
//undefined

obj =
[
{"field" : "DEPARTMAN_NO",
"data" : { "type":"numeric" , "comparison":"eq" , "value":11 }
},
{"field" : "DEPARTMAN_ADI",
"data" : { "type":"string" , "value":"bir" }
}
];
for ( var item in obj ) {
if ( obj[item].field && obj[item].data ) { //check the 'field' and 'data' exist
obj[item].field = {
dept : obj[item].field , //department name is put into a property
type : obj[item].data.type, //so is data.type and data.value..
value: obj[item].data.value //..all are now contained in 'field'
};
delete obj[item].data; //remove the 'data' object
}
}
console.log(obj);

department.type = department.data.type;
department.value = department.data.value;
delete department['data'];

Related

How to change the value of an Array object in Javascript

I have an array object call listOfObjects.
[{"name":"A", "data":"[{"value1":"1","value2":"2"}]"},
{"name":"B", "data":"[{"value1":"1","value2":"2"}]"}]
What I want to do is insert an object into the array where the array is empty.If the array is not empty then do a check on the item inside. If item already exist, do update on the item, else add it to the array. Below is my code
var searchName= "A";
if (listOfObjects.length > 0) {
for (var i = 0; i < listOfObjects.length; i++) {
if (listOfObjects[i].name == searchName) {
listOfObjects[i].data = data;
break;
} else {
insert = {
'name': searchName,
'data': data
};
listOfObjects.push(insert);
}
}
} else {
insert = {
'name': searchName,
'data': data
};
listOfObjects.push(insert);
}
When I run it, even though A already exist, it update the existing item but also add one more time to the listOfObjects. Is there anyway that can achieve what I want? Thanks..
The problem is you're inserting into the array inside your for loop looking for a match. Instead, remember whether you've seen a match and insert after the loop if you haven't. There's also no reason for the length check and no reason to repeat your logic for inserting:
var searchName= "A";
var found = false;
for (var i = 0; !found && i < listOfObjects.length; i++) {
if (listOfObjects[i].name == searchName) {
listOfObjects[i].data = data;
found = true;
}
}
if (!found) {
listOfObjects.push({
'name': searchName,
'data': data
});
}
Note that you can use Array#find (which can be polyfilled for old browsers) to find the entry rather than a for loop if you like:
var searchName= "A";
var entry = listOfObjects.find(function(entry) {
return entry.name == searchName;
});
if (entry) {
entry.data = data;
} else {
listOfObjects.push({
'name': searchName,
'data': data
});
}
First of all change this
[{"name":"A", "data":"[{"value1":"1","value2":"2"}]"},
{"name":"B", "data":"[{"value1":"1","value2":"2"}]"}]
by
[{"name":"A", "data":[{"value1":1,"value2":2}]},
{"name":"B", "data":[{"value1":"1","value2":"2"}]}];
because your list will throw Uncaught SyntaxError: Unexpected identifier
Write another simple function to get the item listOfObjects[i] with selected searchName. Here 'getSearchObject()' function checks the existance of searchName and then add or updates array.
addOrRemoveItem() {
let listOfObjects = [
{ "name": "A", "data": "[{'value1':'1','value2':'2'}]" },
{ "name": "B", "data": "[{'value1':'1','value2':'2'}]" }
],
data = '[{"value1":"1","value2":"2"}]';
var searchName = "C";
if (listOfObjects.length > 0) {
let searchObj = this.getSearchObject(listOfObjects, searchName);
if (searchObj) {
searchObj.data = data;
} else {
let insert = {
"name": searchName,
"data": data
}
listOfObjects.push(insert);
}
} else {
let insert = {
"name": searchName,
"data": data
}
listOfObjects.push(insert);
}
}
getSearchObject(objArr, searchKey) {
var obj = null;
for (let i = 0; i < objArr.length; i++) {
if (objArr[i].name === searchKey) {
obj = objArr[i];
}
}
return obj;
}
A generic solution that recognizes older JS engines (filter instead of find) but does always assume getting passed a list of unique items could be implemented like this ...
function updateList(itemList, item) { // - always assume a list of unique items.
var
itemName = item.name,
listItem = itemList.filter(function (elm) { // - assume `filter`, not find`.
return (elm.name === itemName); // - find/get existing list item by name.
})[0];
if (listItem) {
listItem.data = item.data;
} else {
itemList.push(item)
}
}
var list = [
{ "name": "A", "data": [ { "value1": "A1", "value2": "A2" }] },
{ "name": "B", "data": [ { "value1": "B1", "value2": "B2" }] },
{ "name": "C", "data": [ { "value1": "C1", "value2": "C2" }] }
];
console.log('list : ', list);
updateList(list, { "name": "D", "data": [ { "value1": "D1", "value2": "D2" }] });
updateList(list, { "name": "B", "data": [ { "value1": "b_1", "value2": "b_2", "value3": "b_3" }] });
updateList(list, { "name": "C", "data": [ { "value3": "C3" }] });
console.log('list : ', list);
.as-console-wrapper { max-height: 100%!important; top: 0; }

group by unique values of property

I got array of objects (tasks). Each task has property named 'category' and 'duration'.
var tasks = [
{
_id : "123",
category : "someCategory",
duration: "3432"
},
{
_id : "113",
category : "someCategory",
duration: "23"
},
{
_id : "124",
category : "someCategory 2",
duration: "1343"
},
{
_id : "2124",
category : "someCategory 2",
duration: "1343"
},
{
_id : "7124",
category : "someCategory 5",
duration: "53"
},
{
_id : "34",
category : "someCategory",
duration: "753"
}
]
I'd like to group tasks by category (unique) and sum duration of each category.
Result should be like:
var categories = ["someCategory", "someCategory 2" ... ]
var duration = [ <summary duration of "someCategory">, <summary duration of "someCategory 2">, ... ]
I have groupBy function which gives me all categories. I can find uniqueCategories using Array.prototype.filter but still I have to sum 'duration'.
var categoryMap = groupBy(tasks, 'category');
var uniqueCategories = categoryMap.get('category').filter((x, i, a) => a.indexOf(x) == i);
function groupBy(list, property) {
var map = new Map();
list.forEach(function(item) {
const key = property;
if(!map.has(key)) {
map.set(key, [item[key]])
} else {
map.get(key).push(item[key])
}
})
return map;
}
Then I create array of { key : value } and sum by key i.e.
[
{
someCategory : 3432
},
{
someCategory : 23
}
.
.
.
]
Finally I achieve my goal but code looks messy and isn't readable at all...
Is there better approach to do it in Javascript?
You could just return one object with category: duration.
var tasks = [{"_id":"123","category":"someCategory","duration":"3432"},{"_id":"113","category":"someCategory","duration":"23"},{"_id":"124","category":"someCategory 2","duration":"1343"},{"_id":"2124","category":"someCategory 2","duration":"1343"},{"_id":"7124","category":"someCategory 5","duration":"53"},{"_id":"34","category":"someCategory","duration":"753"}]
var result = tasks.reduce(function(r, e) {
r[e.category] = (r[e.category] || 0) + +e.duration
return r;
}, {})
console.log(result)
var tasks = [{"_id":"123","category":"someCategory","duration":"3432"},{"_id":"113","category":"someCategory","duration":"23"},{"_id":"124","category":"someCategory 2","duration":"1343"},{"_id":"2124","category":"someCategory 2","duration":"1343"},{"_id":"7124","category":"someCategory 5","duration":"53"},{"_id":"34","category":"someCategory","duration":"753"}]
var arr = [];
tasks.forEach(v => arr.push(v.category));
var newArr = [...new Set(arr)];
var arr2 = [];
newArr.forEach(function(v) {
var obj = {};
obj.category = v;
obj.duration = 0;
arr2.push(obj);
});
arr2.forEach(v => tasks.forEach(c => c.category == v.category ? v.duration += parseInt(c.duration) : v));
console.log(arr2);

Remove duplicates and merge JSON objects

I have the following JSON object. I need to remove the duplicates and merge the inner object using plain Javascript. How do I go about doing this?
[{
"id" : 1,
"name" : "abc",
"nodes" :[
{
"nodeId" : 20,
"nodeName" : "test1"
}
]
},
{
"id" : 1,
"name" : "abc",
"nodes" :[
{
"nodeId" : 21,
"nodeName" : "test2"
}
]
}]
Following is the object that I expect as output.
[{
"id" : 1,
"name" : "abc",
"nodes" :[
{
"nodeId" : 20,
"nodeName" : "test1"
},
{
"nodeId" : 21,
"nodeName" : "test2"
},
]
}]
Regards.
Shreerang
First turn the JSON into a Javascript array so that you can easily access it:
var arr = JSON.parse(json);
Then make an array for the result and loop through the items and compare against the items that you put in the result:
var result = [];
for (var i = 0; i < arr.length; i++) {
var found = false;
for (var j = 0; j < result.length; j++) {
if (result[j].id == arr[i].id && result[j].name == arr[i].name) {
found = true;
result[j].nodes = result[j].nodes.concat(arr[i].nodes);
break;
}
}
if (!found) {
result.push(arr[i]);
}
}
Then you can create JSON from the array if that is the end result that you need:
json = JSON.stringify(result);
If your string is called input, then this:
var inter = {};
for (var i in input) {
if (!inter.hasOwnProperty(input[i].name)) {
inter[input[i].name] = input[i].nodes;
inter[input[i].name].name = input[i].name;
inter[input[i].name].id = input[i].id;
}
else
inter[input[i].name] = inter[input[i].name].concat(input[i].nodes)
}
results in:
{"abc":[{"nodeId":20,"nodeName":"test1"},{"nodeId":21,"nodeName":"test2"}]}
You can see how I'm using an intermediate object keyed by whatever the match criterion is. It's an object rather than an array as you asked, but you can iterate it anyway. In fact you're probably better off with this structure than the array you asked for.
BTW, I shoved a couple of text-named properties: "id" and "name" into an array there. They don't show up in JSON.stringify but they're there.

Sorting array into array new based on string

I'm trying to sort a JSON into multiple arrays based on type, my current json is:
// current json file:
{
"res": [
{
"type" : "stream",
"price" : "3.99",
"id" : "13nee"
},
{
"type" : "stream",
"price" : "2.99",
"id" : "8ejwj"
},
{
"type" : "buy",
"price" : "3.99".
"id" : "9akwk"
},
...
]
}
I'm looking to sort it into multiple arrays by type like below:
var sorted = {
"stream" : [
{
"price" : "2.99",
"id" : "8ejwj"
},
{
"price" : ".99",
"id" : "13nee"
},
... // other objects with type: "stream"
],
"buy" : [
{
"price" : "3.99".
"id" : "9akwk"
},
... // other objects with type: "buy"
]
}
I've tried it, but the only solution I can think of is by cases - run if loop, if case matches type, then push object to array. Is there a more elegant solution?
var items = {};
var i = 0;
for(i; i < res.length; i += 1){
var resItem = res[i];
if(items.hasOwnProperty(resItem.type)){
items[resItem.type].push({price:resItem.price, id:resItem.id});
} else {
items[resItem.type] = [{price:resItem.price, id:resItem.id}];
}
}
The properties on JavaScript objects are hashed, so you can dynamically match and generate new objects like above. If you want to apply a well ordering sort, you'll need to apply it to the arrays of the newly generated items object.
Step 1 :
Convert the JSON to a jquery object :
var x = jQuery.parseJSON( jsonString );
Step 2:
Use underscore library's _.groupBy to group :
_.groupBy(x,'type');
There might be some adjustment you need to do for x being array or object.
Edit :
You don't need step1. Just do :
sorted = _.groupBy(json.res,'type');
You could do something like this with ECMA5. This performs, generically, the sort and reduce that you have indicated in your question, so you can add more fields to your data without having to change the routine. It also leaves your original data intact.
Javascript
var original = {
'res': [{
'type': 'stream',
'price': '3.99',
'id': '13nee'
}, {
'type': 'stream',
'price': '2.99',
'id': '8ejwj'
}, {
'type': 'buy',
'price': '3.99',
'id': '9akwk'
}]
},
sorted = {};
original.res.slice().sort(function (a, b) {
a = +(a.price);
b = +(b.price);
if (a < b) {
return -1;
}
if (a > b) {
return 1;
}
return 0;
}).reduce(function (acc, element) {
if (!acc[element.type]) {
acc[element.type] = [];
}
acc[element.type].push(Object.keys(element).filter(function (name) {
return name !== 'type';
}).reduce(function (prev, name) {
prev[name] = element[name];
return prev;
}, {}));
return acc;
}, sorted);
console.log(JSON.stringify(sorted));
Output
{
"stream": [{
"price": "2.99",
"id": "8ejwj"
}, {
"price": "3.99",
"id": "13nee"
}],
"buy": [{
"price": "3.99",
"id": "9akwk"
}]
}
On jsFiddle

Convert one javascript nested object data structure to nested arrays

I am trying to convert a JSON string in a Javascript object literal. I think it is possible with some loops, but i couldn't get it done. The target structure is shown below, "chartData".
Fiddle can be found here: http://jsbin.com/ajemih/13/edit
Here's the JSON data:
{
"1b":{
"allLoad":"130",
"loadMovement":"111",
"allMovement":"111"
},
"1a":{
"allLoad":"910",
"loadMovement":"671",
"allMovement":"280"
},
"systemLoad":"963"
}
This should it look like after the conversion:
chartData = [[['loadMovement', 111],
['allMovement', 120],
['allLoad', 130]],
[['Load+Move', 671],
['allMovement', 280],
['allLoad', 910]]];
I think this would work:
Working demo: http://jsfiddle.net/jfriend00/YmjDR/
var data = {
"1b":{
"allLoad":"130",
"loadMovement":"111",
"allMovement":"111"
},
"1a":{
"allLoad":"910",
"loadMovement":"671",
"allMovement":"280"
},
"systemLoad":"963"
};
var chartData = [];
for (var i in data) {
var item = data[i];
var outer = [];
// skip over items in the outer object that aren't nested objects themselves
if (typeof item === "object") {
for (var j in item) {
var temp = [];
temp.push(j);
temp.push(item[j]);
outer.push(temp);
}
}
if (outer.length) {
chartData.push(outer);
}
}
You could do something like this:
var chartData = []
for(var key in data) {
var properties = data[key];
if(typeof properties === "object") {
var array = [];
for(var propKey in properties) {
array.push([propKey, properties[propKey]])
}
chartData.push(array);
}
}
Check out the fiddle.
You need to map the data manually. Thats actually more a diligent but routine piece of work.
var jsonData = 'your json string';
Object.keys( jsonData ).map(function( key ) {
if( typeof jsonData[ key ] === 'object' ) {
return Object.keys( jsonData[ key ] ).sort(function( a, b ) {
return +jsonData[ key ][ a ] - +jsonData[ key ][ b ];
}).map(function( name ) {
return [ name, jsonData[ key ][ name ] ];
});
}
}).filter( Boolean );
The above code will sort each group by its numeric value and then map a new array in the required style. Since .map() possibly returns undefined values on non-object elements, we need to filter those out before or afterwards.
See http://jsfiddle.net/WjZB2/2/
I had similar problem.
My goal was to convert a list of strings into a valid format for http://ivantage.github.io/angular-ivh-treeview/
This was my starting point:
[
"A\\A1\\Test1",
"A\\A1\\Test2",
"A\\A2\\Test3",
"B\\Test4",
"B\\Test5",
"B\\B1\\Test6",
"B\\B1\\Test7",
"B\\B1\\Test8",
"C\\C1\\C1a\\Test9",
"C\\C1\\C1b\\Test10",
"C\\C2\\C2a\\Test11",
"C\\C2\\C2a\\Test12",
"C\\C2\\C2a\\Test13",
"C\\C3\\Test14",
"C\\Test15",
"C\\Test16"
]
And I needed following format:
[
{
"label": "Selected Tests",
"children": [
{
"label": "A",
"children": [
{
"label": "A1",
"children": [
{
"label": "Test1",
"value": true
},
{
"label": "Test2",
"value": true
}
]
},
{
"label": "A2",
"children": [
{
"label": "Test3",
"value": true
}
]
}
]
}
]
}
]
See my solution https://jsfiddle.net/ydt3gewn/

Categories

Resources