Get value in a multidimensional array - javascript

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

Recursively list nested object keys

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 ]), [])
]), [])

How to get a key from array of objects by its value Javascript

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'));

Filter data inside array object of array object using javascript

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

convert objects array to griddle readable array

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)));

How to use groupBy on object in Javascript?

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)

Categories