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)));
Related
I am storing the prev values in an array of objects, for example [{ActFollow: 'BlN'},{ActSendGift: 'BlY'},{ActSubscribe: 'BlY'}] I want to store the key and values in an object like this {ActFollow: 'BlN',ActSendGift: 'BlY', ActSubscribe: 'BlY'}
const [activityTypes, setActivityTypes] = useState<any>([]); // state
.then((response: any) => {
setActivityTypes((oldArray: any) => [
...oldArray,
{[item.channelSettingTypeId]: response.settingValue},
]);
});
How about this, if the nesting is only one level deep
const data = [{ActFollow: 'BlN',ActSendGift: 'BlY', ActSubscribe: 'BlY'}]
console.log([{...data[0],"hey" : "world"}])
const items = [{ActFollow: 'BlN'},{ActSendGift: 'BlY'},{ActSubscribe: 'BlY'}]
let object = {}
items.forEach(item=>{
for (const [key, value] of Object.entries(item)) {
object = {
...object,
[key]: value
}
}
})
console.log(object)
You can use this simple idea in React also. Just hold on the default empty object in state and update the object.
You can reduce the array of objects into an object.
You can do it by spreading (...) the current object into the resultant object, as shown below:
const
arrOfObjs = [{ ActFollow: "BlN" }, { ActSendGift: "BlY" }, { ActSubscribe: "BlY" }],
obj = arrOfObjs.reduce((res, o) => ({ ...res, ...o }), {});
console.log(obj);
You can also do it using Object.assign, as shown below:
const
arrOfObjs = [{ ActFollow: "BlN" }, { ActSendGift: "BlY" }, { ActSubscribe: "BlY" }],
obj = arrOfObjs.reduce((res, o) => Object.assign(res, o), {});
console.log(obj);
Use Spread Operator
const items = [{ActFollow: 'BlN', Anurag: 26},{ActSendGift: 'BlY'},{ActSubscribe: 'BlY'}]
let obj ={}
items.forEach((item) => {
obj = {
...obj,
...item
}
})
console.log(obj)
I have an object that i am trying to transform
var data = {
"A": {"XY1" : 1},
"B": {"XY2": 12},
"C": {"XY3": 10},
"D": {"XY1": 2}
am trying to transform this to
[
{ "XY1": { 1:"A", 2:"D"}},
{ "XY2": { 12:"B"}},
{ "XY3": { 8:"A", 10:"C"}},
]
(we can ignore the ordering of XY1, XY2 etc)
Here is what i have done so far -
var result = Object.keys(data).flatMap(alphabet => {
return Object.keys(data[alphabet]).map(group => {
return Object.assign({}, {
[group]: { [data[alphabet][group]]: alphabet }
})
});
});
console.log(result);
which prints
[
{"XY1":{"1":"A"}},
{"XY3":{"8":"A"}},
{"XY2":{"12":"B"}},
{"XY3":{"10":"C"}},
{"XY1":{"2":"D"}}
]
However, i want it to be grouped by using reduce(chaining), such as -
var result = Object.keys(data).flatMap(alphabet => {
return Object.keys(data[alphabet]).map(group => {
return Object.assign({}, {
[group]: { [data[alphabet][group]]: alphabet }
})
});
}).reduce((obj, item) => {
});
Is this possible ? How do i group by these dynamic keys?
Help much appreciated !
I'd group first using a hashtable:
const hash = {};
for(const [key, obj] of Object.entries(data)) {
for(const [key2, values] of Object.entries(obj)) {
if(!hash[key2]) hash[key2] = {};
for(const value of [values].flat())
hash[key2][value] = key;
}
}
To then get an array you can use Object.entries:
const result = Object.entries(hash).map(([key, value]) => ({ key, value }));
This is not exactly what you wanted, but to be honest I don't see a sense of having an array of objects with just one key each.
I have a requirement to replace the available keys with the desired keys in an object for which I was trying to execute below code, which later I found out to be incorrect usage of filter for desired output. hence I need help in getting the desired results using es6 array functions.
const columns = Object.keys(someArray).filter((columnName) => {
if (someCheck === "somecheck") {
if (columnName === 'MyName') {
const newcolumnName = `Pranav`;
return newcolumnName;
} else if (columnName === 'YourName') {
const newcolumnName = `Alex`;
return newcolumnName;
}
} else {
return (columnName !== 'sometingelse') ? columnName : '';
}
}
);
Here the someArray is as below:
someArray{
abc:"djfhdjf",
xyz:"ssss",
MyName:"onename",
YourName:"somename",
sometingelse:'somevalue'
}
I am expecting columns to be:
columns{
abc:"djfhdjf",
xyz:"ssss",
Pranav:"onename",
Alex:"somename",
sometingelse:'somevalue'
}
Please suggest how can I achieve the above expected output?
Note: I dont want to use function keyword in callbacks to avoid eslint errors
You could filter the wanted keys for replacement and replace the keys by using a new key and eleting the old one.
const
object = { abc: "djfhdjf", xyz: "ssss", MyName: "onename", YourName: "somename", sometingelse: 'somevalue' },
replacements = { MyName: 'Pranav', YourName: 'Alex', sometingelse: '' };
Object
.keys(object)
.filter(k => k in replacements)
.forEach(k => {
object[replacements[k]] = object[k];
delete object[k];
});
console.log(object);
For generating an object, you could map new objects and assign them to a single object.
const
object = { abc: "djfhdjf", xyz: "ssss", MyName: "onename", YourName: "somename", sometingelse: 'somevalue' },
replacements = { MyName: 'Pranav', YourName: 'Alex', sometingelse: '' },
result = Object.assign(...Object
.entries(object)
.map(([k, v]) => ({ [k in replacements ? replacements[k] : k]: v }))
);
console.log(result);
const obj = {
abc: 'djfhdjf',
xyz: 'ssss',
MyName: 'onename',
YourName: 'somename',
sometingelse: 'somevalue'
};
const newObj = Object.keys(obj).reduce((acc, key) => {
if (key === 'MyName') {
acc.newMyName = obj[key];
} else if (key === 'YourName') {
acc.newYourName = obj[key];
} else {
acc[key] = obj[key];
}
return acc;
}, {});
console.log('newObj = ', newObj);
Here is my approach, a bit long solution, but its on purpose so you can see how to do it simple without too much abstraction:
const someArray = {
abc:"djfhdjf",
xyz:"ssss",
MyName:"onename",
YourName:"somename",
sometingelse:'somevalue'
}
let foo = Object.keys(someArray).map(key => {
if(key === 'MyName') {
return 'Alex'
} else if(key === 'YourName') {
key = 'Pranav'
}
return key;
})
let bar = Object.entries(someArray).map((el, i) => {
el[0] = res[i];
return el;
})
let baz = r.reduce((acc, el)=>{
acc[`${el[0]}`] = el[1];
return acc;
},{})
console.log(baz);
You could use .reduce like so. It uses a similar idea that Nina proposed by using an object to hold your replacements. Here I have used the spread syntax to add the changed key to the accumulated object, along with it's associated value.
const someArray = {abc: "djfhdjf", xyz: "ssss", MyName: "onename", YourName: "somename", sometingelse: 'somevalue'},
toUse = {MyName: "Pranav", YourName: "Alex"}, // define the keys you want to change and what they should change to
res = Object.keys(someArray).reduce((acc, key) =>
({...acc, [key in toUse ? toUse[key] : key]:someArray[key]})
, {});
console.log(res);
I am running a reduce on the keys of some array starting with an empty object. The ...acc spreads out all the properties in the reduced object. ...{ [keysMap[key] || key]: obj[key] } checks if the current key is present in keysMap.If it is present,it uses that key (keysMap[key]) otherwise it just uses the keys of the existing object.(|| key).Hope that makes sense
const renameKeys = (keysMap, obj) =>
Object.keys(obj).reduce(
(acc, key) => ({
...acc,
...{ [keysMap[key] || key]: obj[key] }
}),
{}
)
const columns = renameKeys({'MyName':'Pranav','YourName':'Alex'},someArray)
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 need to group by id and sum, but I need a new object for each result:
let data = [
{"id":"2018", "name":"test", "total":1200},
{"id":"2019", "name":"wath", "total":1500},
{"id":"2019", "name":"wath", "total":1800},
{"id":"2020", "name":"zooi", "total":1000},
]
I have this code that returns just one object with the result
let result = data.reduce(function (r, o) {
(r[o.id])?
r[o.id] += o.total:
r[o.id] = o.total;
return r;
});
But I need some like this:
[
{"id":"2018", "name":"test", "total":1200},
{"id":"2019", "name":"wath", "total":2300},
{"id":"2020", "name":"zooi", "total":1000},
]
How can I do it?
let data =[
{"id":"2018", "name":"test", "total":1200},
{"id":"2019", "name":"wath", "total":1500},
{"id":"2019", "name":"wath", "total":1800},
{"id":"2020", "name":"zooi", "total":1000},
];
let map = data.reduce((prev, next) =>{
if (next.id in prev) {
prev[next.id].total += next.total;
} else {
prev[next.id] = next;
}
return prev;
}, {});
let result = Object.keys(map).map(id => map[id]);
console.log(result);
You can try this:
const result = Object.values(data.reduce((r, o) => (r[o.id]
? (r[o.id].total += o.total)
: (r[o.id] = {...o}), r), {}));
Change your reduce to:
let result = data.reduce(function(acc, obj) { // for each obj in data
if(acc.map.hasOwnProperty(obj.id)) { // if the map contains an object for the current object's id
acc.map[obj.id].total += +obj.total; // then add the current object's total to it
} else { // otherwise
var newObj = Object.assign({}, obj); // create a new object (a copy of the current object)
acc.map[obj.id] = newObj; // add the new object to both the map
acc.data.push(newObj); // ... and the data array
}
return acc;
}, {data: [], map: {}}).data; // the accumulator should have an array for the data objects (which will be our result) and a map object which maps the ids to the objects in the data array. Once our reduce finishes its work, we assign the data array of the accumulator to result
Example:
let data =[ {"id":"2018", "name":"test", "total":1200}, {"id":"2019", "name":"wath", "total":1500}, {"id":"2019", "name":"wath", "total":1800}, {"id":"2020", "name":"zooi", "total":1000} ];
let result = data.reduce(function(acc, obj) {
if(acc.map.hasOwnProperty(obj.id)) {
acc.map[obj.id].total += +obj.total;
} else {
var newObj = Object.assign({}, obj);
acc.map[obj.id] = newObj;
acc.data.push(newObj);
}
return acc;
}, {data: [], map: {}}).data;
console.log(result);
import uniqBy from 'lodash/uniqBy'
export function transform (array) {
const newArray = []
const uniq = uniqBy(array, 'id')
uniq.forEach(item => {
const total = array
.filter(({id}) => item.id === id)
.reduce((sum, current) => sum + current.total, 0)
newArray.push({
...item,
total
})
})
return newArray
}