find value pair in json object using key element - javascript

With reference to question posted here use jQuery's find() on JSON object
I have json object in which i'd like to search value of the element if i passed respective key element to it
Json:
{"RESPONSE":{"#xmlns":"","CODE":"0","SECODE":"0","TXNID":"17527","LASTBALANCE":"-12078.8","SURCHARGE":"2","CUSTOMERDETAILS":{"NAME":"Mr.ABC"}}}
I want to retrieve value Mr.ABC when i passed Name as a key to my function
Code:
console.log(getObjects(ContextObj, 'Name'));
function getObjects(obj, key) {
var objects = [];
for (var i in obj) {
if (!obj.hasOwnProperty(i)) continue;
if (i == key) {
objects.push(obj);
}
}
return objects;
}
It gives output now as
[ ]

Try this:
var data = {"RESPONSE":{"#xmlns":"","CODE":"0","SECODE":"0","TXNID":"17527","LASTBALANCE":"-12078.8","SURCHARGE":"2","CUSTOMERDETAILS":{"NAME":"Mr.ABC"}}};
function find_value(key, inner_key) {
var value = "";
$.each(data.RESPONSE, function (i, k) {
console.log(i, key, i == key)
if (i == key) {
value = k;
return false;
}
});
if (inner_key) {
if (value[inner_key]) {
value = value[inner_key];
}
}
return value;
}
Calling function:
find_value("LASTBALANCE");
find_value("CUSTOMERDETAILS", "NAME");
See DEMO here.

You need to call your code recursive for nested json keys like,
var s={"RESPONSE":{"#xmlns":"","CODE":"0","SECODE":"0","TXNID":"17527","LASTBALANCE":"-12078.8","SURCHARGE":"2","CUSTOMERDETAILS":{"NAME":"Mr.ABC"}}};
console.log(getObjects(s, 'NAME'));
console.log(getObjects(s, 'LASTBALANCE'));
function getObjects(obj, key) {
var objects = [];
for (var i in obj) {
if(typeof obj[i] == 'object'){
return getObjects(obj[i], key); // if it is an object then find the key recursively.
}
if (!obj.hasOwnProperty(i)) continue;
if (i == key) {
return obj[key];
}
}
return '';
}
Working DEMO

Related

Find duplicate values inside array of objects

What is the best way in JavaScript to go over array of object and check if an certain value already exist in one of the property of the array objects?
For example: I have array of objects as follow:
[{name:"team1",members:3},{name:"bestteam",members:4}]
Now I want to add a new object but I want to check that this object property "name" do not exist in the array before adding it
Try this
function checkIfNameExists(arr, newName) {
return arr.some(function(e) {
return e.name === newName;
});
}
where arr is your array and newName is the name to check.
You could also make it less ad hoc by passing the property to compare as a parameter, like so
function checkIfNameExists(arr, prop, newVal) {
return arr.some(function(e) {
return e[prop] ? e[prop] === newVal : false;
});
}
assuming you say an object equals an object if and only if they have the exact same elements and values for each element:
var map = {};
for (var i = 0; i < arr.length; i++) {
var index = JSON.stringify(arr[i]);
if (!map[index]) {
map[index] = 1;
} else {
map[index]++;
}
}
for (var key in map) {
if (map[key] > 1) {
console.log ('duplicate found for:');
console.log (JSON.parse (key));
}
}
simply define an array "arr" with some objects and check it out
You can iterate over the array and iterate over the keys of the array and check if some properties have the wanted value.
var data = [{ prop1: 'one', prop2: 'two' }, { prop3: 'three', prop4: 'four' }];
function find(v, data) {
data.forEach(function (a, i) {
Object.keys(a).forEach(function (k) {
if (a[k] === v) {
document.write(v + ' found in [' + i + '].' + k);
}
});
});
}
find('three', data);
You can use simple loops. Here is function which should help you to find out if key value is in array.
function keyExist(value, array) {
for(var i in array) {
for(var k in array[i])
if(array[i][k] === value) {
console.log(value + ' is in array!');
return true;
}
}
return false;
}
As for you example you can change second loop
for(var k in array[i])
if(k === value) { return true; }
to
if(array[i].name === value) { return true; }
I have no time to respond but here from my previous code maybe some will optimize it...
function JSONRemoveDuplicates(JSONDATA) {
var uniqueNames = [];
$.each(JSONDATA, function (i, el) {
if (!existInJSON(uniqueNames, el) > 0) { uniqueNames.push(el); }
});
return uniqueNames;
}
function existInJSON(jsondata, el) {
var ret = 0;
$(jsondata).each(function (index, data) {
if (data.id == el.id)
ret++;
})
return ret > 0;
}

return key value pair from object whose key matches certain condition with javascript and underscore

var obj = {
"M_18-24":413109,
"F_18-24":366159,
"F_25-34":265007,
"U_25-34":1214,
"U_35-44":732
}
I want to return an object with key value pairs whose keys start with either "M" or "F". So the final object would look like
var obj = {
"M_18-24":413109,
"F_18-24":366159,
"F_25-34":265007
}
I've tried things like _.filter(obj, function(v,k) { return /^[MF]/.test(k) })...
this will do the trick:
function filte_obj_FM (inp)
{
var ret = {};
for ( var k in inp)
{
if ( k[0] == "M" || k[0] == "F" )
{
ret[k] = inp[k];
}
}
return ret;
}
see console output (F12 +-> see console) here: http://jsfiddle.net/vH3ym/2/
You can try
for (var prop in obj) { console.log(prop) }
It will give you the corresponding properties, then you can add your logic like
if(prop.indexOf('M'))
This should work:
var obj = {
"M_18-24":413109,
"F_18-24":366159,
"F_25-34":265007,
"U_25-34":1214,
"U_35-44":732
}
var filtered = {}
for(var key in obj) {
if(key[0] === "M" || key[0] === "F"){
filtered[key] = obj[key]
}
}
Another version this time using reduce:
// create a new underscore function that will return the properties from an object that pass a given predicate
_.mixin({ filterProperties: function(obj, predicate){
return _.reduce(obj, function(memo, value, key){
if( predicate(key) ){
memo[key] = value;
}
return memo;
}, {});
}});
// A couple of predicates that we can use when calling the new function
function isMale(key){
return key[0] == 'M';
}
function isFemale(key){
return key[0] == 'F';
}
// and finally getting the data we want:
var males = _.filterProperties( obj, isMale );
var females = _.filterProperties( obj, isFemale );
Here's my solution:
_.filter(_.keys(obj), function(key) {
return key.match(/U/);
}).forEach(function(kv) {
delete obj[kv];
});
I think all of yours are good and I voted them up. Thanks!

Removing the duplicate keys of a JSON array and getting its JSON path

I have the JSON below:
{"response":{"result":{"Leads":{"row":[{"LEADID":"849730000000063017","SMOWNERID":"849730000000061001"},{"LEADID":"849730000000063015","SMOWNERID":"849730000000061001","HIII":"hello"},{"LEADID":"849730000000063007","SMOWNERID":"849730000000061001","BYEE":"tata"},{"LEADID":"849730000000063005","SMOWNERID":"849730000000061001"},{"LEADID":"849730000000063003","SMOWNERID":"849730000000061001"},{"LEADID":"849730000000063001","SMOWNERID":"849730000000061001"}]}},"uri":"/crm/private/json/Leads/getMyRecords"}}
I have the requirement to get the JSON path, for which I used the code below:
var str={"response":{"result":{"Leads":{"row":[{"LEADID":"849730000000063017","SMOWNERID":"849730000000061001",},
{"LEADID":"849730000000063015","SMOWNERID":"849730000000061001"},
{"LEADID":"849730000000063007","SMOWNERID":"849730000000061001","HIII":"hello"},
{"LEADID":"849730000000063005","SMOWNERID":"849730000000061001","BYEE":"tata"},
{"LEADID":"849730000000063003","SMOWNERID":"849730000000061001"},
{"LEADID":"849730000000063001","SMOWNERID":"849730000000061001"}]}},
"uri":"/crm/private/json/Leads/getMyRecords"}}
var keys = [];
getKeys(keys,str, '');
for(var i=0; i<keys.length; i++) {
var d=new Array();
d=keys[i][1].replace(/^\.|\.$/g, '')
console.log(keys[i][0] + '=' +d)
}
function getKeys(keys, obj, path) {
for(key in obj) {
var currpath = path+'.'+key;
keys.push([key, currpath]);
if(typeof(obj[key]) === 'object') {
getKeys(keys, obj[key], currpath);
}
}
}
Below is the output:
response=response
result=response.result
Leads=response.result.Leads
row=response.result.Leads.row
0=response.result.Leads.row.0
LEADID=response.result.Leads.row.0.LEADID
SMOWNERID=response.result.Leads.row.0.SMOWNERID
1=response.result.Leads.row.1
LEADID=response.result.Leads.row.1.LEADID
SMOWNERID=response.result.Leads.row.1.SMOWNERID
HIII=response.result.Leads.row.1.HIII
2=response.result.Leads.row.2
LEADID=response.result.Leads.row.2.LEADID
SMOWNERID=response.result.Leads.row.2.SMOWNERID
BYEE=response.result.Leads.row.2.BYEE
3=response.result.Leads.row.3
LEADID=response.result.Leads.row.3.LEADID
SMOWNERID=response.result.Leads.row.3.SMOWNERID
4=response.result.Leads.row.4
LEADID=response.result.Leads.row.4.LEADID
SMOWNERID=response.result.Leads.row.4.SMOWNERID
5=response.result.Leads.row.5
LEADID=response.result.Leads.row.5.LEADID
SMOWNERID=response.result.Leads.row.5.SMOWNERID
uri=response.uri
The array elements keys are repetitive (ie) LEADID and SMOWNERID are repetitive in the array. I want to remove the duplicates of the entire array and display the output like this:
response=response
result=response.result
Leads=response.result.Leads
row=response.result.Leads.row
0=response.result.Leads.row.0
LEADID=response.result.Leads.row.0.LEADID
SMOWNERID=response.result.Leads.row.0.SMOWNERID
HIII=response.result.Leads.row.0.HIII
BYEE=response.result.Leads.row.0.BYEE
uri=response.uri
I am stuck here, any help regarding this will be very helpful.
Modify the function getKeys to this :
function getKeys(keys, obj, path) {
for(key in obj) {
var currpath = path+'.'+key;
keys.push([key, currpath]);
if(typeof(obj[key]) === 'object') {
if(obj[key] instanceof Array){ //added check for array
keys.push(['0', currpath+'.0']);
getKeys(keys, obj[key][0], currpath+'.0');
}
else
getKeys(keys, obj[key], currpath);
}
}
}
Update
function getKeys(keys, obj, path) {
for(key in obj) {
var currpath = path+'.'+key;
addKeys(key, currpath);
//keys.push([key, currpath]);
if(typeof(obj[key]) === 'object') {
getKeys(keys, obj[key], currpath);
}
}
}
function addKeys(key, currpath) { //check before adding
present = keys.map(function(x){return(x[1].split('.').slice(-1)[0])});
if (present.indexOf(key)==-1){
keys.push([key, currpath]);
}
}
The answer is not exactly like you want but is the closest I could get. Also the values you have given for HIII and BYEE are wrong. Lastly it is possible to have same keys at different levels, but I am only matching the name of key. It may not work if same keyname is used at different levels.
Another approach is to change the keys to object from array - change the var keys = [] to var keys = {} and then change the getKeys method as follow:
function getKeys(keys, obj, path) {
for(key in obj) {
var currpath = path+'.'+key;
if(keys[key])
continue;
keys[key] = currpath;
if(typeof(obj[key]) === 'object') {
getKeys(keys, obj[key], currpath);
}
}
}
Now you will also need to change the way you print the values after the return from getKeys since now keys is not an array rather an object.

Sort basic json object

I have a very simple json object,
{
"costA": 9617,
"costB": 11100,
"costC": 13208,
"costD": 9910
}
Is it possible to sort this json (in javascript) to get the resultant?
{
"costA": 13208,
"costB": 11100,
"costC": 9910,
"costD": 9617
}
Note: key names can change..
The below JavaScript gives the result you're after: {costA: 13208, costB: 11100, costC: 9910, costD: 9617}:
var obj = JSON.parse('{"costA": 9617, "costB": 11100, "costC": 13208, "costD": 9910}');
var values = [], keys = [], key, i;
for (key in obj) {
keys.push(key);
values.push(obj[key]);
}
values.sort(function (a, b) { return b-a; });
keys.sort();
for (i = 0; i < keys.length; ++i) {
key = keys[i];
val = values[i];
obj[key] = val;
}
console.log(obj);
See also fiddle.

How to flatten or combine member names into one list?

For example if I have something like so:
var Constants = {
scope:{
namespaceA: { A_X: "TEST_AX" , A_Y: "TEST_AY" },
namespaceN: { N_X: "TEST_NX" , N_Y: "TEST_NY" }
}
_mapping: [],
getMapping: function(){...}
}
var flattenList = flatten(Constants.scope); //returns ["TEST_AX","TEST_AY","TEST_NX","TEST_NY"]
var anotherWayFlattened = flatten(Constants.scope.namespaceA,Constants.scope.namespaceB); //returns same result as above
EDIT: one way would be to iterate over the scope via for-each loop but I was looking for something more elegent?
DOUBLE EDIT: ok I just whipped something up like so:
var flattenedList = (function(list){
var flatList = []
$.each(list,function(i,items){
for(var p in items) flatList.push(items[p]);
})
return flatList;
})([Constants.scope.namespaceA,Constants.scope.namespaceB]);
but was wondering if we can avoid passing in the particular property and just pass in Constants and search for the list of namespaces
[Constants.scope.namespaceA,Constants.scope.namespaceB]
I'm wondering why you pass the sub-objects explicitly in an array. Why not just pass the whole Constants.scope object?
var flattenedList = (function(obj){
var flatList = []
for (var prop in obj) {
var items = obj[prop];
for (var p in items)
flatList.push(items[p]);
}
return flatList;
})(Constants.scope);
From your comment it looks like you wanted this:
var flattenedList = (function(obj, test){
var flatList = []
for (var prop in obj) {
if (!test(prop))
continue;
var items = obj[prop];
for (var p in items)
flatList.push(items[p]);
}
return flatList;
})(Constants, function(name) {
return name.substr(0, 9) == "namespace";
// or maybe
return /^namespace[A-Z]$/.test(name);
});
if you wanted to recurse to any (non cyclical!) depth, you could do this :
function flattenList(list, accumulator){
accumulator = accumulator || [];
for(var p in list){
if(list.hasOwnProperty(p)) {
if(typeof list[p] === "string") {
accumulator.push(list[p]);
} else if(typeof list[p] === "object") { // this is not a reliable test!
flattenList(list[p], accumulator);
}
}
}
return accumulator;
}
This code makes a number of assumptions - we only have strings at the end of our objects etc. Alternatively, if you know the depth in advance, your current solution can be optimized by using concat :
var flattenedList = (function(list){
return Array.prototype.concat.apply([], list);
})([Constants.scope.namespaceA,Constants.scope.namespaceB]);
Here's an approach that allows for deeper nesting. I know that wasn't part of the goals, but I found it a more interesting problem. :-)
var flatten = (function() {
var toString = Object.prototype.toString, slice = Array.prototype.slice;
var flatten = function(input, output) {
var value;
output = (toString.call(output) == "[object Array]") ? output : [];
for (name in input) {if (input.hasOwnProperty(name)) {
value = input[name];
if (toString.call(value) == "[object Object]") {
flatten(value, output);
} else {
output.push(value);
}
}};
return output;
};
var merge = function(first, second) {
return first.concat(second);
}
return function() {
return slice.call(arguments).map(flatten).reduce(merge);
};
}());
This allows either approach:
flatten(Constants.scope);
flatten(Constants.scope.namespaceA, Constants.scope.namespaceN);
You can pass in as many separate arguments as you like, or one argument. They'll all be searched to arbitrary depths.
For some environments, you might have to shim Array.prototype functions map and reduce.

Categories

Resources