How to change key number? - javascript

I have this object:
a = {"formData": {
"total": "60.00",
"tr0_RTN": "PZH",
"tr0_amount": "10.00",
"tr2_RTN": "SUB",
"tr2_amount": "30.00",
"tr7_RTN": "KFC",
"tr7_amount": "20.00",
}};
How can I change the key sequence to this:
a = {"formData": {
"total": "60.00",
"tr0_RTN": "PZH",
"tr0_amount": "10.00",
"tr1_RTN": "SUB",
"tr1_amount": "30.00",
"tr2_RTN": "KFC",
"tr2_amount": "20.00",
}};
Anyway I could do this with native or lodash?

You could get all relevant keys, look for the parts and build new consecutive numbers.
Then assign the old values to the new properties and delete the old keys.
old key new key action
---------- ---------- --------------------------------------------
tr0_RTN tr0_RTN no, because old key and new key are the same
tr0_amount tr0_amount same as above
tr2_RTN tr1_RTN create new key, delete old key
tr2_amount tr1_amount same
tr7_RTN tr2_RTN same
tr7_amount tr2_amount same
var a = { "formData": { "total": "60.00", "tr0_RTN": "PZH", "tr0_amount": "10.00", "tr2_RTN": "SUB", "tr2_amount": "30.00", "tr7_RTN": "KFC", "tr7_amount": "20.00", } };
Object.keys(a.formData).filter(function (k) {
return k.indexOf('tr') === 0;
}).sort(function (a, b) {
return a.match(/\d+/) - b.match(/\d+/);
}).forEach(function (k) {
var m = k.match(/(\d+)_(.*)/),
kk;
if (m[1] !== this.last) {
this.counter++;
this.last = m[1];
}
kk = 'tr' + this.counter + '_' + m[2];
if (k !== kk) {
a.formData[kk] = a.formData[k];
delete a.formData[k];
}
}, { counter: -1, last: '' });
console.log(a);

You may do as follows;
var data = {"formData": { "total": "60.00",
"tr0_RTN": "PZH",
"tr0_amount": "10.00",
"tr2_RTN": "SUB",
"tr2_amount": "30.00",
"tr7_RTN": "KFC",
"tr7_amount": "20.00",
}
},
propsToDel = ["tr2_RTN", "tr2_amount", "tr7_RTN", "tr7_amount"],
propsToIns = ["tr1_RTN", "tr1_amount", "tr2_RTN", "tr2_amount"],
newData = propsToIns.reduce((o,p,i) => { o.formData[p] = o.formData[propsToDel[i]];
delete o.formData[propsToDel[i]];
return o;
},data);
console.log(newData);

I imagine you're having a form with tr rows, and you'd like to rearrange them. As the indeces are pretty much random, you can use this function to organize/reindex them.
var keys = Object.keys(a["formData"]);
var formData = {};
var index = 0;
for (var i = 0; i < keys.length; i++) {
var key = keys[i];
if (key.indexOf('tr') == 0) {
if (key.indexOf('_RTN') >= 0) {
key = 'tr' + index + '_RTN';
} else if (key.indexOf('_amount') >= 0) {
key = 'tr' + index + '_amount';
}
if ((formData.hasOwnProperty('tr' + index + '_RTN')
|| formData.hasOwnProperty('tr' + index + '_amount'))
&& !formData.hasOwnProperty(key)) {
index++;
}
}
formData[key] = a["formData"][keys[i]];
}
a["formData"] = formData;
This will rebuild your object with altered keys for the respective _RTN and _amount items.

Related

Serialize complex object with nested array and objects to build query params

Example of complex object which i want to serialize, so I can use it in url as query param
var query = {
"page": {
"number": 1,
"size": 50
},
"sort": "engagement_total",
"sort_direction": "asc",
"filters": {
"engagement_total": {
"type": "range",
"value": [
21,
46
]
}
}
}
JSON.stringify(query)
result with stringify
'{"page":{"number":1,"size":50},"sort":"engagement_total","sort_direction":"asc","filters":{"engagement_total":{"type":"range","value":[21,46]}}}'
Desired result
filters%5Bengagement_total%5D%5Btype%5D=range&filters%5Bengagement_total%5D%5Bvalue%5D%5B%5D=21&filters%5Bengagement_total%5D%5Bvalue%5D%5B%5D=46&page%5Bnumber%5D=1&page%5Bsize%5D=50&sort=engagement_total&sort_direction=asc
let obj = {
"page": {
"number": 1,
"size": 50
},
"sort": "engagement_total",
"sort_direction": "asc",
"filters": {
"engagement_total": {
"type": "range",
"value": [
21,
46
]
}
}
}
var flattenObj = function(data) {
var result = {};
function recurse(cur, prop) {
if (Object(cur) !== cur) {
result[prop] = cur;
} else if (Array.isArray(cur)) {
for (var i = 0, l = cur.length; i < l; i++)
recurse(cur[i], prop + "[" + i + "]");
if (l == 0)
result[prop] = [];
} else {
var isEmpty = true;
for (var p in cur) {
isEmpty = false;
recurse(cur[p], prop ? prop + "[" + p + "]" : p);
}
if (isEmpty && prop)
result[prop] = {};
}
}
recurse(data, "");
return result;
};
let output = flattenObj(obj);
let url = Object.entries(output).map(elem => (elem[0].replace(/\[[0-9]+\]/, '[]') + "=" + elem[1])).join("&")
console.log("url:", url)
console.log("encodeURI:", encodeURI(url))

Format a javascript object into a specific structure

i have a javascript object as follows
obj = {"account_id-0":null,"option_item_id-0":1,"value-0":"wer","account_id-1":null,"option_item_id-1":2,"value-1":"kkk","account_id-2":null,"option_item_id-2":3,"value-2":"qqqqq"
....
"account_id-n":null,"option_item_id-n":6,"value-n":"see"
}
From the above object, i need to create the following structure
{"0": {
account_id: null,
option_item_id: 1,
value: "wer"
},
"1": {
account_id: null,
option_item_id: 2,
value: "kkk"
},
"2": {
account_id: null,
option_item_id: 2,
value: "qqqqq"
},
.
.
.
"n": {
account_id: null,
option_item_id: 6,
value: "see"
}
}
Any idea on how to implement this?
You can iterate through the all the keys, and use Array#reduce to contruct the resultant object.
let obj = {
"account_id-0": null,
"option_item_id-0": 1,
"value-0": "wer",
"account_id-1": null,
"option_item_id-1": 2,
"value-1": "kkk",
"account_id-2": null,
"option_item_id-2": 3,
"value-2": "qqqqq",
"account_id-n": null,
"option_item_id-n": 6,
"value-0": "see"
};
let result = Object.keys(obj).reduce((res, item) => {
let [key, index] = item.split('-');
if (!res[index]) {
res[index] = {};
}
res[index][key] = obj[item];
return res;
}, {});
console.log(result);
var obj = {
"account_id-0": null,
"option_item_id-0": 1,
"value-0": "wer",
"account_id-1": null,
"option_item_id-1": 2,
"value-1": "kkk",
"account_id-2": null,
"option_item_id-2": 3,
"value-2": "qqqqq"
};
var props = [];
function getObj(ind) {
for (var p in props) {
if (ind === p) {
return props[p];
}
}
}
for (var prop in obj) {
var parts = prop.split('-');
var key = parts[0];
var indx = parts[1];
var tmp = getObj(indx);
if (tmp == undefined) {
var x = {};
x[indx] = {};
x[indx][key] = obj[prop];
props.push(x);
} else {
tmp[indx][key] = obj[prop];
}
}
console.log(props);
This should be the straight forward way of maniplulating the object array with simple split() function.
Try this:
var keys = Object.keys(obj), i = 0
var arr = [], o = {}
for(var k in keys) {
if(keys[k].match(/\d*$/m) == i) {
o[keys[k].replace(/-\d*$/m,'')] = obj[keys[k]]
} else {
i++
arr.push(o)
o = {}
}
}
Here I am using an array instead of an object with the keys "0", "1", " 2", ... "n". I think it's way more convenient.

Collapse nested objects into flat map with dotted properties

I have an object like this
{
"CPU": {
"Architecture": {
"X86": 0,
"Other": 0,
"X86_64": 6
}
},
"Platform": {
"Os": {
"Mac": 0,
"Linux": 5,
"Other": 0,
"Windows": 0
}
}
}
How to to convert it to map like this?
"CPU.Architecture.X86": 0
"Platfrom.Os.Mac":0
"Platfrom.Os.Linux":5
Can there already be ready-made solutions?
If your goal is to concatenate nested object property keys, there is no built-in function for that. However, it is quite simple to implement your own solution:
// Concatenate nested object property keys with a dot:
function dotnotation(obj, dst = {}, prefix = '') {
Object.entries(obj).forEach(([key, val]) => {
if (val && typeof val == 'object') dotnotation(val, dst, prefix + key + '.');
else dst[prefix + key] = val;
});
return dst;
}
// Example:
console.log(dotnotation({a:{b:1, c:2}, d:3})); // {'a.b':1, 'a.c':2, 'd':3}
Object.entries() is part of the upcoming ES2017 standard.
You could try something like this, assuming your object are simply created from data:
function flatten(obj, prev = "", res = {}){
for(f in obj){
if (obj.hasOwnProperty(f)){
if(obj[f].constructor === Object){
prev = prev + f + ".";
flatten(obj[f], prev, res);
}else{
res[prev + f] = obj[f];
}
}
}
return res;
}
let a = {
"CPU": {
"Architecture": {
"X86": 0,
"Other": 0,
"X86_64": 6
}
},
"Platform": {
"Os": {
"Mac": 0,
"Linux": 5,
"Other": 0,
"Windows": 0
}
}
};
console.log(flatten(a))
It will use the for... in loop.
// more consisely
function flatten(obj, prev = "", res = {}){
for(f in obj){
if (obj.hasOwnProperty(f)){
if (obj[f].constructor === Object){
if(typeof obj[f] !== "object") res[prev + f] = obj[f];
else flatten(obj[f], prev + f + ".", res);
}
}
}
return res;
}

Remove duplicate values from json array using angular js

I want to remove duplicates from the following json array
$scope.array = [
{"name":"aaa","key":"1"},
{"name":"bbb","key":"2"},
{"name":"aaa","key":"1"},
{"name":"ccc","key":"3"},
{"name":"bbb","key":"2"}
];
I tried following code but its not working
var ids = {};
$scope.array.forEach(function (list) {
ids[list.name] = (ids[list.name] || 0) + 1;
});
var finalResult = [];
$scope.array.forEach(function (list) {
if (ids[list.name] === 1) finalResult.push(student);
});
console.log(finalResult);
This is the expected result.
$scope.array = [
{"name":"aaa","key":"1"},
{"name":"bbb","key":"2"} ,
{"name":"ccc","key":"3"}
];
You can do something like this using Array#filter
$scope = {};
$scope.array = [{
"name": "aaa",
"key": "1"
}, {
"name": "bbb",
"key": "2"
}, {
"name": "aaa",
"key": "1"
}, {
"name": "ccc",
"key": "3"
}, {
"name": "bbb",
"key": "2"
}];
var ids = {};
$scope.array = $scope.array.filter(function(v) {
var ind = v.name + '_' + v.key;
if (!ids[ind]) {
ids[ind] = true;
return true;
}
return false;
});
console.log($scope.array);
You can use the unique filter.
<tr ng-repeat="arr in array | unique: 'key'" >
<td> {{ arr.name }} , {{ arr.key }} </td>
</tr>
You can use
$scope.array = = [{
"testada": "ecom",
"id": "27"
}, {
"testada": "alorta",
"id": "27"
}, {
"testada": "france24",
"id": "23"
}, {
"testada": "seloger",
"id": "23"
}];
var arr = [],
collection = [];
$scope.array.forEach(json_all, function (index, value) {
if ($.inArray(value.id, arr) == -1) {
arr.push(value.id);
collection.push(value);
}
});
console.log(json_all);
console.log(collection);
console.log(arr);
$scope.array = [
{"name":"aaa","key":"1"},
{"name":"bbb","key":"2"},
{"name":"aaa","key":"1"},
{"name":"ccc","key":"3"},
{"name":"bbb","key":"2"}
];
var newArr = []; //this will be new array with no duplicate value
for (var i = 0; i < $scope.array.length; i++) {
if(!ifContains($scope.array[i])){
newArr.push($scope.array[i]);
}
}
function ifContains(obj){
debugger
var flag = false;
for(var i = 0; i < newArr.length; i++){
if(newArr[i].name == obj.name && newArr[i].key == obj.key )
return true;
else
flag = false;
}
return flag;
}
It can be very simply done by pure JS. An invention of Object.prototype.compare() will help us enormously. Let's see how it works;
Object.prototype.compare = function(o){
var ok = Object.keys(this);
return typeof o === "object" && ok.length === Object.keys(o).length ? ok.every(k => this[k] === o[k]) : false;
};
var myArray = [
{"name":"aaa","key":"1"},
{"name":"bbb","key":"2"},
{"name":"aaa","key":"1"},
{"name":"ccc","key":"3"},
{"name":"bbb","key":"2"}
],
filtered = myArray.reduce((p,c) => p.findIndex(f => c.compare(f)) == -1 ? p.concat(c) : p,[]);
console.log(JSON.stringify(filtered));
Note: Object.prototype.compare() v.01 won't do deep object comparison as of now.
var uniqueList = _.uniq($scope.array, function (item) {
return item.key;
});
console.log(uniqueList);
use underscore.js, anyone helps out so post later.
you can use pure javascript!
uniqueArray = a.filter(function(item, pos) {
return a.indexOf(item) == pos;
})
in your case:
var finalResult = [];
finalResult = $scope.array.filter(function(item, pos) {
return array.indexOf(item) == pos;
})

Iterate and search values in a object-literal having multiple levels

Here is what I want to do:
I have a tree (javascript object-literal structure) with multiple levels.
I have a value of a particular key of this object.
I want to search for this exact key-value pair in the structure and return the value of another key as an output.
For clarity following is my object literal:
{
"nodeId": 1081,
"appId": 150,
"displayText": "Welcome here",
"Nodes": [
{
"nodeId": 2000,
"appId": 150,
"displayText": "Buy",
"parentNodeId": 1081,
"Nodes": [
{
"nodeId": 2003,
"appId": 150,
"displayText": "tCars",
"parentNodeId": 2000,
"Nodes": [
{
"nodeId": 2006,
"appId": 150,
"displayText": "Diesel",
"parentNodeId": 2003,
"Nodes": [
{
"nodeId": 2008,
"appId": 150,
"displayText": "Price", //This is what I want as return value.
"parentNodeId": 2006,
"Nodes": [],
"nodeCode": "RN_1_1_2_1_3_2_4_1",
"parentCode": "RN_1_1_2_1_3_2",
"jumpToNode": "RN_1_1" //here is the value that I have with me.
}
],
"nodeCode": "RN_1_1_2_1_3_2",
"parentCode": "RN_1_1_2_1"
}
],
"concatWithHeader": false,
"nodeCode": "RN_1_1_2_1",
"parentCode": "RN_1_1"
}
],
"nodeCode": "RN_1_1",
"parentCode": "RN"
}
],
"nodeCode": "RN",
"parentCode": "ROOT_NODE"
}
2. Value that I have with me is "RN_1_1" against jumpToNode
3. I want to search in this object literal and get the value of the key displayText
I searched and tried few things for this but couldnt get the logic to iterate over the inner Nodes objects.
Method I wrote so far:
function getObjects(tree){
var searchkey="RN_1_1";
var displayText = "displayText";
var nodeCode = "nodeCode";
var returnText;
if (tree.hasOwnProperty(nodeCode)) {
var obj = tree[nodeCode];
if(obj == searchkey){
returnText = tree[displayText]; //gives me the return text
break;
}
else{
//here I should iterate over the inner `Nodes` and get the required value.
}
}
}
Please help.
Thanks.
I think you can do something like this which works recursively:
function findProperty(obj, prop, val, propToFetch) {
var answer;
if (obj.hasOwnProperty(prop) && obj[prop] === val) {
return obj[propToFetch];
}
for (var i = 0, len = obj.Nodes.length; i < len; i++) {
answer = findProperty(obj.Nodes[i], prop, val, propToFetch);
if (answer !== null) {return answer;}
}
return null;
}
var result = findProperty(data, "jumpToNode", "RN_1_1", "displayText");
Working demo here: http://jsfiddle.net/jfriend00/EjC5V/
Accordingly to your JSON object you can use this way:
var searchKey="RN_1_1",
displayText = "displayText",
nodeCode = "nodeCode",
returnText,
treeSearch = function (obj, searchKey) {
if (obj[nodeCode] === searchKey) {
returnText = obj[displayText];
} else {
if (obj['Nodes'][0]) {
treeSearch(obj['Nodes'][0], searchKey);
} else {
returnText = null
}
}
};
treeSearch(JSONdata, 'RN_1_1_2_1_3_2');
I have flattened the array using the nodeId to be easier to search through it.
After you flatten the array you can filter it as you wish(i suggest using underscorejs.org)
Here is the live example. The result is displayed in the console.
function flattenNodes (obj, newArr) {
if (obj && obj.Nodes) {
var nodes = obj.Nodes;
delete(obj.Nodes);
newArr[obj.nodeId] = obj;
return flattenNodes(nodes.pop(), newArr);
} else {
return newArr;
}
};
var flattenArr = flattenNodes(arr, new Array());
function findInJumpToNode(find) {
for(key in flattenArr) {
if (flattenArr[key] && flattenArr[key]['jumpToNode']) {
if (flattenArr[key]['jumpToNode'] == find) {
return flattenArr[key];
}
}
}
}
var found = findInJumpToNode('RN_1_1');
console.log(found);
You can use recursion to handle your case.
Check out this sample on jsFiddle.
var nodes= [getNodes()];
alert(getObjects(nodes));
function getObjects(tree){
var searchkey="RN_1_1_2_1_3_2_4_1";
var displayText = "displayText";
var nodeCode = "nodeCode";
var returnText;
if(tree.length > 0)
{
if(tree[0]["nodeCode"] === searchkey)
{
return tree[0][displayText];
}
if(typeof tree[0]["Nodes"] === "undefined")
{
return;
}
return getObjects(tree[0]["Nodes"]);
}
}

Categories

Resources