Access data from response using javascript - javascript

I am using api which return me this response:-
{
VJiQND:
{
optin: 'double',
is_default: 'no',
from_email: 'xxxxxxx#gmail.com',
name: 'ding',
reply_to_email: 'xxxxxxx#gmail.com',
created_on: '2015-05-18 11:32:37',
from_name: 'Xa'
},
VJj3KAS:
{
optin: 'double',
is_default: 'yes',
from_email: 'xxxx#gmail.com',
name: 'xtusxx',
reply_to_email: 'xxxxx#gmail.com',
created_on: '2015-05-18 09:09:43',
from_name: 'Ads'
}
}
now I want to get VJj3KAS if from_name equals to 'Ads' I try filter function but it didn't work it throw me an error can you please help me to get that value.
Thanks

The filter function works for arrays and what you have there is a map. You must simply iterate through the map key/value pairs and check if they match your condition.
function getFilteredKeys(map, filter) {
var filteredKeys = [];
for (var key in map) {
if (filter(key, map[key])) {
filteredKeys.push(key);
}
}
return filteredKeys;
}
Usage:
var keys = getFilteredKeys(apiResult, function(key, value){
return value.from_name && value.from_name === 'Ads';
});

Related

React: Calling filter on Object.keys

A React component is passed a state property, which is an object of objects:
{
things: {
1: {
name: 'fridge',
attributes: []
},
2: {
name: 'ashtray',
attributes: []
}
}
}
It is also passed (as a router parameter) a name. I want the component to find the matching object in the things object by comparing name values.
To do this I use the filter method:
Object.keys(this.props.things).filter((id) => {
if (this.props.things[id].name === this.props.match.params.name) console.log('found!');
return (this.props.things[id].name === this.props.match.params.name);
});
However this returns undefined. I know the condition works because of my test line (the console.log line), which logs found to the console. Why does the filter method return undefined?
Object.keys returns an array of keys (like maybe ["2"] in your case).
If you are interested in retrieving the matching object, then you really need Object.values. And if you are expecting one result, and not an array of them, then use find instead of filter:
Object.values(this.props.things).find((obj) => {
if (obj.name === this.props.match.params.name) console.log('found!');
return (obj.name === this.props.match.params.name);
});
Be sure to return that result if you use it within a function. Here is a snippet based on the fiddle you provided in comments:
var state = {
things: {
1: {
name: 'fridge',
attributes: []
},
2: {
name: 'ashtray',
attributes: []
}
}
};
var findThing = function(name) {
return Object.values(state.things).find((obj) => {
if (obj.name === name) console.log('found!');
return obj.name === name;
});
}
var result = findThing('fridge');
console.log(result);
You need to assign the result of filter to a object and you get the result as the [id]. You then need to get the object as this.props.things[id]
var data = {
things: {
1: {
name: 'fridge',
attributes: []
},
2: {
name: 'ashtray',
attributes: []
}
}
}
var name = 'fridge';
var newD = Object.keys(data.things).filter((id) => {
if (data.things[id].name === name) console.log('found!');
return (data.things[id].name === name);
});
console.log(data.things[newD]);

how to grep this Javascript object array?

I have the following object structure:
var mapData =
{
Summary:
{
ReportName: 'Month End Report'
},
NortheastRegion:
{
Property1: 123,
RegionName: 'Northeast'
},
SoutheastRegion:
{
Property1: 456,
RegionName: 'Southeast'
},
}
I want to write a grep function that returns an array of region names. The following function is not returning any values:
var regions = $.grep(mapData, function(n,i)
{
return n.RegionName;
});
What am I missing here?
$.grep is for filtering arrays. Your structure isn't an array. $.grep is also just for filtering, but you're talking about both filtering (leaving out Summary) and mapping (getting just the region names).
Instead, you can use
Object.keys and push:
var regions = [];
Object.keys(mapData).forEach(function(key) {
var entry = mapData[key];
if (entry && entry.RegionName) {
regions.push(entry.RegionName);
}
});
Object.keys, filter, and map:
var regions = Object.keys(mapData)
.filter(function(key) {
return !!mapData[key].RegionName;
})
.map(function(key) {
return mapData[key].RegionName;
});
A for-in loop and push:
var regions = [];
for (var key in mapData) {
if (mapData.hasOwnProperty(key)) {
var entry = mapData[key];
if (entry && entry.RegionName) {
regions.push(entry.RegionName);
}
}
}
...probably others.
That's an object, not an array. According to the jQuery docs, your above example would work if mapData were an array.
You can use lodash's mapValues for this type of thing:
var regions = _.mapValues(mapData, function(o) {
return o.RegionName;
});
ES6:
const regions = _.mapValues(mapData, o => o.RegionName)
As stated in jQuery.grep() docs, you should pass an array as data to be searched, but mapData is an object. However, you can loop through the object keys with Object.keys(), but AFAIK you'll have to use function specific for your case, like:
var mapData =
{
Summary:
{
ReportName: 'Month End Report'
},
NortheastRegion:
{
Property1: 123,
RegionName: 'Northeast'
},
SoutheastRegion:
{
Property1: 456,
RegionName: 'Southeast'
},
};
var keys = Object.keys(mapData),
result = [];
console.log(keys);
keys.forEach(function(key) {
var region = mapData[key].RegionName;
if (region && result.indexOf(region) == -1) {
result.push(region);
}
});
console.log(result);
// Short version - based on #KooiInc answer
console.log(
Object.keys(mapData).map(m => mapData[m].RegionName).filter(m => m)
);
$.grep is used for arrays. mapData is an object. You could try using map/filter for the keys of mapData, something like:
var mapData =
{
Summary:
{
ReportName: 'Month End Report'
},
NortheastRegion:
{
Property1: 123,
RegionName: 'Northeast'
},
SoutheastRegion:
{
Property1: 456,
RegionName: 'Southeast'
},
};
var regionNames = Object.keys(mapData)
.map( function (key) { return mapData[key].RegionName; } )
.filter( function (name) { return name; } );
console.dir(regionNames);
// es2105
var regionNames2 = Object.keys(mapData)
.map( key => mapData[key].RegionName )
.filter( name => name );
console.dir(regionNames2);
Just turn $.grep to $.map and you would good to go.
var regions = $.map(mapData, function(n,i)
{
return n.RegionName;
});

What is the best way to convert an array of strings into an array of objects?

Let's say I have an array of emails:
['a#gmail.com', 'b#gmail.com', 'c#gmail.com']
I need to convert it into an array of objects that looks like this:
[
{
id: 'a#gmail.com',
invite_type: 'EMAIL'
},
{
id: 'b#gmail.com',
invite_type: 'EMAIL'
},
{
id: 'c#gmail.com',
invite_type: 'EMAIL'
}
]
In order to do that, I have written the following code:
$scope.invites = [];
$.each($scope.members, function (index, value) {
let inviteMember = {
'id': value,
invite_type: 'EMAIL'
}
$scope.invites.push(inviteMember);
});
Is there any better way of doing this?
Since you're already using jQuery, you can use jQuery.map() like this:
var originalArray = ['a#gmail.com', 'b#gmail.com', 'c#gmail.com']
var newArray = jQuery.map(originalArray, function(email) {
return {
id: email,
invite_type:'EMAIL'
};
});
jQuery.map() translates all items in a given array into a new array of items. The function I am passing to jQuery.map() is called for every element of the original array and returns a new element that is written to the final array.
There is also the native Array.prototype.map() which is not supported in IE8. If you're not targeting IE8 or if you use a polyfill, then you can use the native .map():
var newArray = originalArray.map(function(email) {
return {
id: email,
invite_type:'EMAIL'
};
});
This pattern
targetArray = []
sourceArray.forEach(function(item) {
let x = do something with item
targetArray.push(x)
})
can be expressed more concisely with map:
targetArray = sourceArray.map(function(item) {
let x = do something with item
return x
})
in your case:
$scope.invites = $scope.members.map(function(value) {
return {
id: value,
invite_type: 'EMAIL'
}
});

Alternative for _.invert() using underscore library

I need to change the existing map swapping keys into values and values into keys. As there is duplicate values in my map for the keys I cannot use _.invert() of underscore library.
function map() {
return {
'eatables': {
apple: 'fruits',
orange: 'fruits',
guava: 'fruits',
brinjal: 'vegetables',
beans: 'vegetables',
rose: 'flowers',
}
}
}
var reverseMap = _.invert(map()['eatables']);
// invert function works for distinct values.
console.log (reverseMap);
// which is giving Object {fruits: "guava", vegetables: "brinjal",flowers:"rose"}
But i am expecting an output as
Object {fruits: ["apple","orange","guava"], vegetables: ["brinjal","beans"], flowers:"rose"}
I tried as below, i just stuck how to find whether map value is distinct or multiple?
var newObj = invert(map()['eatables']);
_.each(newObj, function(key) {
if (Array.isArray(key)) {
_.each( key, function(value) {
console.log(value);
});
} else {
console.log("else:"+key);
}
});
function invert(srcObj) {
var newObj = {};
_.groupBy(srcObj, function(value, key ) {
if (!newObj[value]) newObj[value] = []; //Here every thing is array, can i make it string for values which are unique.
newObj[value].push(key);
});
return newObj;
}
Let me any alternative using underscore library.
You can use this function. This function uses Object.keys to generate an array containing the keys of the object passed in input. Then, it accesses the values of the original object and use them as key in the new object. When two values map to the same key, it pushes them into an array.
function invert(obj) {
var result = {};
var keys = Object.keys(obj);
for (var i = 0, length = keys.length; i < length; i++) {
if (result[obj[keys[i]]] instanceof Array) {
result[obj[keys[i]]].push(keys[i])
} else if (result[obj[keys[i]]]) {
var temp = result[obj[keys[i]]];
result[obj[keys[i]]] = [temp, keys[i]];
} else {
result[obj[keys[i]]]=keys[i];
}
}
return result;
}
https://jsfiddle.net/6f2ptxgg/1/
You can use the underscore each to iterate through your data and push the result in an array. It should give you your expected output.
function customInvert(data) {
var result = {};
_.each(data, function (value, key) {
if (_.isUndefined(result[value])) {
result[value] = key;
} else if(_.isString(result[value])) {
result[value] = [result[value], key];
} else {
result[value].push(key)
}
});
return result;
}
customInvert({
apple: 'fruits',
orange: 'fruits',
guava: 'fruits',
brinjal: 'vegetables',
beans: 'vegetables',
rose: 'flowers',
})

How to loop through specific keys in nested object?

I want to pull specific parts (definitely not all) from this object:
var metadata = {
cat: {
id: 'id',
name: 'kitty',
},
dog: {
id: 'id',
name: 'spot',
owner: {
name: 'ralph',
}
}
//tons of other stuff
};
I would like to do something like this:
var fields = ['cat.id', 'dog.name', 'dog.owner.name'];
fields.forEach( function(key) {
console.log(metadata[key]); //obv doesn't work
});
This is a simplified scenario where I'm trying to validate specific fields in metadata. Is there a straightforward way to do this?
Split the path to extract individual keys, then use a reducer to resolve the value, then map the results:
var path = function(obj, key) {
return key
.split('.')
.reduce(function(acc, k){return acc[k]}, obj)
}
var result = fields.map(path.bind(null, metadata))
//^ ['id', 'spot', 'ralph']
Now you can log them out if you want:
result.forEach(console.log.bind(console))

Categories