Swap javascript object index by name - javascript

My javascript object looks like the example below, I am wondering how I should write a swap function to change the element position in the object. For example, I want to swap two elements from position 1 to 2 and 2 to 1.
{
element_name_1 : {
//.. data
}
element_name_2 : {
//.. data
}
element_name_3 : {
//.. data
}
element_name_4 : {
//.. data
}
}
Now I want to swap element_name_2 with element_name_1.

As Miles points out, your code is probably broken and should use an array. I wouldn't use it, nor is it tested, but it is possible.
var data = {
element_name_1: {},
element_name_2: {},
element_name_3: {},
element_name_4: {}
}
console.log(data);
var swap = function(object, key1, key2) {
// Get index of the properties
var pos1 = Object.keys(object).findIndex(x => {
return x === key1
});
var pos2 = Object.keys(object).findIndex(x => {
return x === key2
});
// Create new object linearly with the properties swapped
var newObject = {};
Object.keys(data).forEach((key, idx) => {
if (idx === pos1)
newObject[key2] = object[key2];
else if (idx === pos2)
newObject[key1] = object[key1];
else
newObject[key] = object[key];
});
return newObject;
}
console.log(swap(data, "element_name_1", "element_name_2"));

Have a look at the code, may this solve the problem
function swapFunction(source, destination) {
var tempValu,
sourceIndex;
for ( i = 0; i < Arry.length; i++) {
for (var key in Arry[i]) {
Ti.API.info('key : ' + key);
if (source == key) {
tempValu = Arry[i];
sourceIndex = i;
}
if (destination == key) {
Arry[sourceIndex] = Arry[i];
Arry[i] = tempValu;
return Arry;
}
}
}
}
JSON.stringify(swapFunction("key_1", "key_3")); // [{"key_3":"value_3"},{"key_2":"value_2"},{"key_1":"value_1"},{"key_4":"value_4"},{"key_5":"value_5"}]
Let me know if this works.
Good Luck & Cheers
Ashish Sebastian

Related

A way to convert an object with keys of . seperated strings into a JSON object

I'm trying to figure out a way to turn and object like this :
{ "test.subtest.pass" : "test passed", "test.subtest.fail" : "test failed" }
into JSON like this:
{ "test": { "subtest": { "pass": "test passed", "fail": "test failed" }}}
sometimes there may be duplicate keys, as above perhaps there would be another entry like "test.subtest.pass.mark"
I have tried using the following method and it works but it's incredibly ugly:
convertToJSONFormat() {
const objectToTranslate = require('<linkToFile>');
const resultMap = this.objectMap(objectToTranslate, (item: string) => item.split('.'));
let newMap:any = {};
for (const [key,value] of Object.entries(resultMap)) {
let previousValue = null;
// #ts-ignore
for (const item of value) {
// #ts-ignore
if (value.length === 1) {
if(!newMap.hasOwnProperty(item)) {
newMap[item] = key
} // #ts-ignore
} else if (item === value[value.length - 1]) {
if(typeof previousValue[item] === 'string' ) {
const newKey = previousValue[item].toLowerCase().replace(/\s/g, '');;
const newValue = previousValue[item];
previousValue[item] = {};
previousValue[item][newKey] = newValue;
previousValue[item][item] = key;
} else {
previousValue[item] = key;
}
} else if (previousValue === null) {
if (!newMap.hasOwnProperty(item)) {
newMap[item] = {};
}
previousValue = newMap[item];
} else {
if (!previousValue.hasOwnProperty(item)) {
previousValue[item] = {}
previousValue = previousValue[item];
} else if (typeof previousValue[item] === 'string') {
const newValue = previousValue[item];
previousValue[item] = {};
previousValue[item][item] = newValue;
} else {
previousValue = previousValue[item];
}
}
}
}
return newMap;
}
We can utilize recursion to make the code a little less verbose:
function convertToJSONFormat(objectToTranslate) {
// create root object for the conversion result
const result = {};
// iterate each key-value pair on the object to be converted
Object
.entries(objectToTranslate)
.forEach(([path, value]) => {
// utilize a recursive function to write the value into the result object
addArrayPathToObject(result, path.split("."), value);
});
return result;
}
function addArrayPathToObject(root, parts, value) {
const p = parts.shift();
// base-case: We attach the value if we reach the last path fragment
if (parts.length == 0) {
root[p] = value
return;
}
// general case: check if root[p] exists, otherwise create it and set as new root.
if(!root[p]) root[p] = {};
addArrayPathToObject(root[p], parts, value)
}
This function utilizes the fact that objects are pass-by-reference to recursively traverse through the object starting at its root until setting the desired value.
You can add error-handling and other such concerns as necessary for your use.
#Meggan Naude, toJson function copies json object to reference obj for provided keys and value.
const p = { "test.subtest.pass" : "test passed", "test.subtest.fail" : "test failed" };
const result = {} ;
const toJson = (obj, keys, value) => {
if (keys?.length === 1) {
obj[keys[0]] = value;
return obj
} else {
const k = keys.splice(0, 1)
if (k in obj) {
toJson(obj[k], keys, value)
} else {
obj[k] = {};
toJson(obj[k], keys, value)
}
return obj
}
}
Object.keys(p).forEach(key => toJson(result, key.split('.'), p[key]))
console.log(result);

Serialization of JS object with different logic for object's properties

Hi I need to convert the the numeric values of my object to string. But different properties has different transformation rules.
My sample object:
{
name: "Name"
sRatio: 1.45040404
otherMetric: 0.009993
}
I use JSON.stringify to convert my initial object.
let replacemet = {}
JSON.stringify(metrics[0], function (key, value) {
//Iterate over keys
for (let k in value) {
if ((k !== "sRatio") || (k !== "name")) {
replacemet[k] = (100*value[k]).toFixed(2) + "%"
} else {
if( k === "name") {
replacemet[k] = "yo!"+value[k]
} else{
replacemet[k] = value[k].toFixed(2)
}
}
}
})
But my conditions are not triggered and all properties are converting on the same manner.
The job of the replacer callback is not to fill in some global replacemet object but rather to return a new value.
I think you are looking for something along the lines of
JSON.stringify(sample, function (key, value) {
if (key == "sRatio") {
return value.toFixed(2);
} else if (key == "name") {
return "yo!"+value;
} else if (typeof value == "number") {
return (100*value).toFixed(2) + "%"
} else {
return value;
}
})
Try using switch block that will be really good for this. Detailed description on switch.
let replacemet = {}
JSON.stringify(metrics[0], function (key, value) {
//Iterate over keys
for (let k in value) {
switch(k) {
case "name":
replacemet[k] = "yo!"+value[k];
break;
case "sRatio":
replacemet[k] = value[k].toFixed(2);
break;
default:
replacemet[k] = value[k].toFixed(2);
}
}
})
Hope to help you . I add when dynamic property
metrics =
[
{
name: "Name",
sRatio: 1.45040404,
otherMetric:0.009993
},
{
name: "Name1",
sRatio: 2.45040404,
otherMetric: 1.009993
}
]
;
let source = JSON.stringify(metrics);
let arrJson = new Array();
//arrJson = {};
metrics.forEach(function(value){
let replacemet = {};
for(var k in value) {
if( k.toString().trim() == "name") {
replacemet[k] = "yo!"+value[k] ;
}
else
if ( ( k.toString().trim() !== "sRatio") && ( k.toString().trim() !== "name")) {
replacemet[k] = (100* value[k] ).toFixed(2).toString() + "%" ;
} else {
replacemet[k] = value[k].toFixed(2) ;
}
}
arrJson.push(JSON.stringify(replacemet)) ;
});
console.log(arrJson);

Traversing an object and picking out key/value

Im trying to create arrays from an keys in an object. I might have an object in this structure:
$scope.myobj = {
'level1': {
'level1Sub1': {
'result': 'level1-level1Sub1-result'
},
'level1Sub2': {
'result': 'level1-level1Sub2-result'
}
},
'level2': {
'level2Sub1': {
'result': 'level2-level2Sub1-result'
},
'level2Sub2': {
'result': 'level2-level2Sub2-result'
}
}
}
Elements on the same level goes in the same array.
So in this case the result should be:
TopLevelArr = [level1, level2]
SecondLevelArr = [level1Sub1, level1Sub2,level2Sub1,level2Sub2]
Im using jquery to traverse the whole object:
var path = "";
$.each($scope.myobj, walker);
function walker(key, value) {
var savepath = path;
path = path ? (path + "." + key) : key;
console.log(path)
if (value !== null && typeof value === "object") {
// Recurse into children
$.each(value, walker);
}
path = savepath;
}
This should be pretty close if I could find a way to pass the key into the proper array based on its level.
http://jsfiddle.net/bald1/ys05m1s8/2/
Help appreciated. Thank you.
You could use a iterative and recursive approach for getting all keys.
function getKeys(o) {
function iter(o, i) {
var k = Object.keys(o);
keys[i] = keys[i] || [];
k.forEach(function (kk) {
if (keys[i].indexOf(kk) < 0) {
keys[i].push(kk);
}
if (o[kk] !== null && typeof o[kk] === 'object') {
iter(o[kk], i + 1);
}
});
}
var keys = [];
iter(o, 0);
return keys;
}
var $scope = {};
$scope.myobj = { 'level1': { 'level1Sub1': { 'result': 'level1-level1Sub1-result' }, 'level1Sub2': { 'result': 'level1-level1Sub2-result' } }, 'level2': { 'level2Sub1': { 'result': 'level2-level2Sub1-result' }, 'level2Sub2': { 'result': 'level2-level2Sub2-result' } } };
console.log(getKeys($scope.myobj));
.as-console-wrapper { max-height: 100% !important; top: 0; }
var level=0;
var levelarray=[];
function looptrough(obj){
for(key in obj){
if(typeof obj[key]=="object"){
level++;
looptrough(obj[key]);
level--;
}
levelarray[level]=levelarray[level] || {};
levelarray[level][key]=obj[key];
}
}
looptrough({a:true;b:{c:true}});
Levelarray should now contain:
0:{a:true;b:{c:true}}
1:{c:true}
I thought using jquery is quite unecessary in that case, thats why i used for in...

Getting nested obj value

Given the following obj:
var inputMapping = {
nonNestedItem: "someItem here",
sections: {
general: "Some general section information"
}
};
I'm writing a function to get that data by passing in a string "nonNestedItem" or in the nested case "sections.general". I'm having to use an eval and I was wondering if there was maybe a better way to do this.
Here is what I have so far and it works okay. But improve!
function getNode(name) {
var n = name.split(".");
if (n.length === 1) {
n = name[0];
} else {
var isValid = true,
evalStr = 'inputMapping';
for (var i=0;i<n.length;i++) {
evalStr += '["'+ n[i] +'"]';
if (eval(evalStr) === undefined) {
isValid = false;
break;
}
}
if (isValid) {
// Do something like return the value
}
}
}
Linky to Jsbin
You can use Array.prototype.reduce function like this
var accessString = "sections.general";
console.log(accessString.split(".").reduce(function(previous, current) {
return previous[current];
}, inputMapping));
Output
Some general section information
If your environment doesn't support reduce, you can use this recursive version
function getNestedItem(currentObject, listOfKeys) {
if (listOfKeys.length === 0 || !currentObject) {
return currentObject;
}
return getNestedItem(currentObject[listOfKeys[0]], listOfKeys.slice(1));
}
console.log(getNestedItem(inputMapping, "sections.general".split(".")));
You don't need to use eval() here. You can just use [] to get values from an object. Use a temp object to hold the current value, then update it each time you need the next key.
function getNode(mapping, name) {
var n = name.split(".");
if (n.length === 1) {
return mapping[name];
} else {
var tmp = mapping;
for (var i = 0; i < n.length; i++) {
tmp = tmp[n[i]];
}
return tmp;
}
}

How do I reference the "title" given the id?

var data = {};
data.event = [
{
"id":"998",
"title":"Foo",
"thumb":"",
"source":""
},
{
"id":"999",
"title":"Bar",
"thumb":"",
"source":""
}
]
Given that id=998 I need to extract the value of the "title" and I'm a bit lost as to the proper syntax.
You can iterate with $.each() and check to see if the ID matches, and then write the value of title to a variable.
var title;
$.each(data.event, function(i,e) {
if (this.id==='998') {
title=this.title;
return false;
}
});
FIDDLE
function titleFromId(id) {
for (var i = 0, l = data.event.length; i < l; i += 1) {
if (data.event[i].id === id) {
return data.event[i].title;
}
}
}
var title = titleFromId('998');
You need to loop over the event array. For each item, if item.id is the value you are looking for, then return item.title.
Something like the following:
function findTitleById(desiredId) {
var title, item;
for (var i = data.event.length - 1; i >= 0; i--){
item = data.event[i];
if (item.id === desiredId) {
title = item.title;
break;
}
}
return title;
}
There are more advanced ways to do this, but I would understand the above before attempting them.
You can use $.each() function:
$.each(data.event, function(i, v){
alert(v.id + " " + v.title)
})
http://jsfiddle.net/NGALP/

Categories