Hi i have something like:
var obj = {
level1 : {
level2 : 'value'
}
};
Also another object:
var returnData = {
value: "level1.level2",
anotherThing: "level1"
};
I want to loop through all the keys from the returnData object and get those values from the obj object. I have this but can't get the wanted value for the key value in returnData:
var dataToreturn = [];
$.each(returnData, function(k, v) {
dataToreturn[k] = obj[v];
});
So the final result would be:
dataToreturn[value] = 'value';
dataToreturn[anotherThing] = {
level2 : 'value'
};
https://jsfiddle.net/3u4vxwc5/8/
You can use both forEach() and reduce(). forEach to loop object keys and then split() each value at . and then use reduce() to loop those values and add to array.
var obj = {
level1: {
level2: 'value'
}
};
var returnData = {
value: "level1.level2",
anotherThing: "level1"
};
var dataToreturn = [];
Object.keys(returnData).forEach(function(e) {
var keys = returnData[e].split('.')
keys.reduce(function(r, e, i) {
if (keys[i + 1] && r[e]) return r[e]
else if (r[e]) dataToreturn.push(r[e])
return r;
}, obj)
})
console.log(dataToreturn)
var obj = {
level1 : {
level2 : 'value'
}
};
var returnData = {
value: "level1.level2",
anotherThing: "level1"
};
Object.keys(returnData).forEach(key=>returnData[key]=returnData[key].split(".").reduce((val,key)=>val[key],obj)||returnData[key]);
console.log(returnData);
Iterate over all keys of return Data and reduce it to a value.
Related
i have an nested object as such:
options = {
religous: {
kosher: {
value: 'Kosher',
chosen: false
},
halal: {
value: 'Halal',
active: false
},
},
vegan: {
value: 'Vegan',
active: false
}
}
It contains nested objects of varying sizes. I would like to get an Array containing the values of any value propery. So for the above object the desired output would be:
['Kosher', 'Halal', 'Vegan']
Order doesn't really matter.
I tried to do so recursively as such:
getListOfLabels = obj => {
const lst = []
for (let key in obj) {
if (obj[key].value) lst.push(obj[key].value)
else return getListOfLabels(obj[key])
}
return lst
}
but I keep getting a RangeError: Maximum call stack size exceeded error.
Any suggestions?
The for...in loop assigns the key. To get the value use obj[key]. If the key is value add to lst, if it's an object, call getListOfLabels on it, and spread the results into lst.push():
const options = {"religous":{"kosher":{"value":"Kosher","chosen":false},"halal":{"value":"Halal","active":false}},"vegan":{"value":"Vegan","active":false}}
const getListOfLabels = obj => {
const lst = []
for (let key in obj) {
const val = obj[key] // get the value
if (key === 'value') lst.push(val) // if the key name is "value" push to lst
else if(typeof val === 'object') lst.push(...getListOfLabels(val)) // if type of value is object, iterate it with getListOfLabels and push the results into lst
}
return lst
}
const result = getListOfLabels(options)
console.log(result)
You could take a recursive approach and check if the object contains a value key.
function getValues(object, key) {
if (key in object) return [object[key]];
return Object.values(object).reduce((r, v) => {
if (v && typeof v === 'object') r.push(...getValues(v, key));
return r;
}, []);
}
var options = { religous: { kosher: { value: 'Kosher', chosen: false }, halal: { value: 'Halal', active: false } }, vegan: { value: 'Vegan', active: false } };
console.log(getValues(options, 'value'));
Here's a succinct approach using reduce :-D
const getValues = options => Object.values(options)
.reduce((acc, optionObj) => (
optionObj.value ? [ ...acc, optionObj.value ] : [
...acc,
...Object.values(optionObj).reduce((arr, { value }) => ([ ...arr, value ]), [])
]), [])
I have a collection which looks like this:
var array = [
{ 'key1': 'val1'},
{ 'key2': 'val2'}
];
I want a function which takes array and value as parameters and returns key of that value (values are unique)
getKey(array, 'val1');
>>>>> output: 'key1'
I tried the following solution but it says key property is not defined:
getKey(array, value) {
var keys = [];
array.forEach(function(element) {
for (key in element) {
if(value == element[key]) {
keys.push(key);
}
}
})
return keys[0];
},
var arr = [{ 'key1': 'val1'}, { 'key2': 'val2'}];
function getKey(data,value) {
let keys=[];
data.forEach(function(element) {
for (key in element) {
if(element[key]==value)
keys.push(key);
}
});
return keys
}
console.log(getKey(arr, 'val1'))
Create an inverse object with value as key and key as value. And then finally access the value from object as key.
var array = [{ 'key1': 'val1'},{ 'key2': 'val2'}];
function getKey(arr, val) {
let obj = arr.reduce((a,c) => {
Object.entries(c).forEach(([k,v]) => a[v]=k);
return a;
}, {})
return obj[val];
}
console.log(getKey(array, 'val1'));
In pure JS you can take all the entries, flatten them and simply search the value in all couples and if found then just take the first entry of that couple.
[].concat(...array.map(Object.entries)).find(a=>a[1]=='val1')[0]
Here is an working example:
var array = [{'key1': 'val1'}, {'key2': 'val2'}, {'key3': 'val3'}],
getKey = (arr,v)=>[].concat(...arr.map(Object.entries)).find(a=>a[1]==v)[0];
console.log(getKey(array, 'val2'));
console.log(getKey(array, 'val3'));
However, I will suggest you to use lodash (or underscore, or lazy) to make it more cleaner and simple.
Here is a lodash approach:
_.findKey(_.merge({}, ...array), s=>s=='val1')
Here is a woking example:
var array = [{'key1': 'val1'}, {'key2': 'val2'}, {'key3': 'val3'}],
getKey = (arr,v)=>_.findKey(_.merge({}, ...arr), s=>s==v);
console.log(getKey(array, 'val2'));
console.log(getKey(array, 'val3'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.min.js"></script>
You can also try this:
var arr = [{ 'key1': 'val1'}, { 'key2': 'val2'}];
function getKey(arr, val) {
var result = 'not found';
arr.forEach(obj => {
for (var key in obj) {
if(obj[key] === val) result = key;
}
});
return result;
}
console.log(getKey(arr, 'val1'));
console.log(getKey(arr, 'value'));
I am trying to filter data inside array object of array object, Please find below code for more information.
var data = [
{
name:'testdata1',
subdata:[{status:'fail'},{status:'success'}]
},
{
name:'testdata2',
subdata:[{status:'fail'},{status:'success'}]
}
]
Expected Data:
var successdata = [
{
name:'testdata1',
subdata:[status:'success'}]
},
{
name:'testdata2',
subdata:[status:'success'}]
}
];
var FailureData =[
{
name:'testdata1',
subdata:[{status:'fail'}]
},
{
name:'testdata2',
subdata:[{status:'fail'}]
}
];
I missed curly braces,So i am updating
Hope this helps.
const data = [{
name: 'testdata1', subdata: [{status: 'fail'}, {
status:
'success'
}]
},
{
name: 'testdata2', subdata:
[{status: 'success'}, {status: 'fail'}]
}
];
const filterData = (data, status) => data.reduce((acc, val) => {
const sub = val.subdata.map((v) => v.status === status ? ({ name: val.name, subdata: [v] }) : null).filter(f => f !== null);
return acc.concat(sub);
}, []);
const successData = filterData(data, 'success');
const failureData = filterData(data, 'fail');
console.log('successData', successData);
console.log('failureData', failureData);
You could map your arrays using Array.map():
var successData = data.map(item => ({name: item.name, subdata:[{status:'success'}]})
What I guess you want to do is filter the array based on subdata status.
I also guess that what subdata should have is just the status property and your code would be: var data = [{name:'testdata1',subdata:[{status:'fail'},{status:'success'}] }.
Then you want to look in the subdata array and find which data have success and failure in them.
So what you could be looking for is this:
var successData = data.filter(sdata => {
var successFlag=false;
sdata.subdata.forEach(subdata=>{
if (subdata.status==='success'){
successFlag = true;
}
}
return successFlag;
}
The same with the failureData.
For more information you could check the Array.prototype.filter function:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter
P.S. As mentioned in a comment to your question as well, your subdata array cannot be an object with two of the same property
var data = [{name:'testdata1',subdata:[{status:'fail'}, {status:'success'}] },{name:'testdata2',subdata:[{status:'success'}, {status:'fail'}] }]
var successData = filterByStatus('success', data);
var failureData = filterByStatus('fail', data);
function filterByStatus(status, data) {
return data.map(d => {
var newObj = Object.assign({}, d);
newObj.subdata = newObj.subdata.filter(s => s.status === status);
return newObj;
});
}
console.log('successData', successData);
console.log('failureData', failureData);
one of possible ways to do what you want if you have one success property in your object
I'm fetching json data with ajax. Then I want to output it in Griddle using griddle-react. The problem is I cannot convert my array to a Griddle readable array.
After the ajax fetch i made a callback function:
function convert(obj) {
console.log(obj);
Object.keys(obj).forEach(function (key) {
let format = JSON.stringify(obj[key]);
console.log(format);
self.setState(() => ({ data: key[format] }));
});
}
The first console.log output looks like this:
{
{
"BTC": {
"opening_price": "9845000",
"closing_price": "9967000",
"min_price": "9814000",
"max_price": "10047000",
"average_price": "9928071.5654",
"units_traded": "7242.04659594",
"volume_1day": "7242.04659594",
"volume_7day": "73491.92898643",
"buy_price": "9967000",
"sell_price": "9968000"
},
}
}
My functions makes it look like this: (second console.log):
{
"opening_price": "9846000",
"closing_price": "9965000",
"min_price": "9814000",
"max_price": "10047000",
"average_price": "9929422.0905",
"units_traded": "7200.46713802",
"volume_1day": "7200.467F13802",
"volume_7day": "73395.33311647",
"buy_price": "9959000",
"sell_price": "9964000"
}
I want it to convert to the following array, basically adding the name item, and thereafter Griddle can read it:
{
"name": "BTC",
"opening_price": "9845000",
"closing_price": "9967000",
"min_price": "9814000",
"max_price": "10047000",
"average_price": "9928071.5654",
"units_traded": "7242.04659594",
"volume_1day": "7242.04659594",
"volume_7day": "73491.92898643",
"buy_price": "9967000",
"sell_price": "9968000"
},
What I'm doing wrong here? I'm sure its pretty close to what I want, but I can't figure it out at this point.
You can use Object.entries to get the keys and values. Use Object.assign to make new objects
var obj = {
"BTC": {"opening_price": "9845000","closing_price": "9967000","min_price": "9814000","max_price": "10047000","average_price": "9928071.5654","units_traded": "7242.04659594","volume_1day": "7242.04659594","volume_7day": "73491.92898643","buy_price": "9967000","sell_price": "9968000"}
}
var newObj = Object.entries(obj).reduce((c, [i, v]) => Object.assign(c, {name: i}, v), {});
console.log(newObj);
If you have several keys, you can use map
var obj = {
"BTC": {"opening_price": "9845000","closing_price": "9967000","min_price": "9814000","max_price": "10047000","average_price": "9928071.5654","units_traded": "7242.04659594","volume_1day": "7242.04659594","volume_7day": "73491.92898643","buy_price": "9967000","sell_price": "9968000"},
"OTH": {"opening_price": "9845000","closing_price": "9967000","min_price": "9814000","max_price": "10047000","average_price": "9928071.5654","units_traded": "7242.04659594","volume_1day": "7242.04659594","volume_7day": "73491.92898643","buy_price": "9967000","sell_price": "9968000"},
}
var newArr = Object.entries(obj).map(([i, v]) => Object.assign({}, {name: i}, v));
console.log(newArr);
Without including date property
var obj = {
"KNC": {"opening_price": "2731","closing_price": "2788","min_price": "2693","max_price": "2849","average_price": "2790.5368","units_traded": "3178032.25814499211673","volume_1day": "3178032.25814499211673","volume_7day": "110687333.315264505902311000","buy_price": "2783","sell_price": "2788"},
"date": "1525269153470"
}
var newObj = Object.entries(obj).reduce((c, [i, v]) => i !== 'date' ? Object.assign(c, {name: i}, v) : c, {});
console.log(newObj);
Can you update your function to have this line in it?
obj[key]["name"] = key
function convert(obj) {
console.log(obj);
Object.keys(obj).forEach(function (key) {
obj[key]["name"] = key;
let format = JSON.stringify(obj[key]);
console.log(format);
//self.setState(() => ({ bithumbData: key[format] }));
});
}
function convert(obj){
var parentKey = Object.keys(obj)[0];//Getting parent first element key
obj = obj[parentKey];
var newObj = {}; //Creating new empty jason object
newObj['name'] = parentKey; //key apply as name element to new jason object
for(var key in obj) //looping each child element
newObj[key] = obj[key]; //child applying to new jason object
return newObj;
}
console.log(JSON.stringify(convert(obj)));
I have an object as below:
obj = {
'fruita' : 'eat',
'fruitb' : 'eat',
'fruitc' : 'throw',
'fruitd' : 'throw'
}
output = {
'eat' : ['fruita','fruitb'],
'throw' : ['fruitc','fruitd']
}
How to apply _.groupBy in order to get the list of eat and throw fruits seperately?
We can turn our object to an array of key-value pairs:
var keyValues = Object.keys(obj).map(key => ({ key, value: obj[key] }));
And then we can perform a reduce to construct our object:
var values = keyValues.reduce((acc, kv) => {
if (typeof acc[kv.value] === 'undefined') {
acc[kv.value] = [];
}
acc[kv.value].push(kv.key);
return acc;
}, {});
No lodash necessary!
You could use a for..in loop to set properties of output object to values of obj , push obj properties to items within array at output
var obj = {
'fruita' : 'eat',
'fruitb' : 'eat',
'fruitc' : 'throw',
'fruitd' : 'throw'
}
var output = {};
for (var prop in obj) {
if (!output[obj[prop]]) {
output[obj[prop]] = [];
output[obj[prop]].push(prop)
} else {
output[obj[prop]].push(prop)
}
}
console.log(output)