Javascript get key of nested JSON object? - javascript

I have a json response that looks like the image below. I want to get all dates from the json and store in an array.
function buyOption(){
var ticker = document.getElementById('ticker').value;
fetch("https://stock-and-options-trading-data-provider.p.rapidapi.com/options/JPM", {
.then(response => response.json())
.then(data => {
dataset = data;
console.log(dataset['options'])
loadTable()
})
.catch(err => {
console.log(err);
});
function loadTable(){
expiration_dates = []
dates = dataset['options']
// console.log(JSON.parse(dates))
var keys = [];
for(var k in dates) keys.push(k);
console.log(keys)// returns ["0","1","2",3","5",6","9","10","11"]
console.log(dates[0].value) // returns undefined
}
}
goal is to have expiration_dates = ["2020-08-21","2020-08-28"]

You can try this. This will give you only the expiration dates.
var obj = {
"options": [{
"10-2-2001": "",
"someOtherProp": ""
}, {
"20-2-2001": "",
"someOtherProp": ""
}]
}
var expDates = obj.options.map(o=>Object.keys(o)[0])
console.log(expDates)
Refs:
Array.map()
Object.keys()

Try this
let result = dataSet.options.map(x => Object.keys(x));
console.log(result.flat(1))

A simple array map should do the trick and use Object.keys() array to get first key from each object in your data array
const dates = dataset['options'].map(o => Object.keys(o)[0])
console.log(dates)
<script>
const dataset = {
options: [{
'2013-12-22': {
puts: [],
calls: []
}},
{'2013-02-15': {
puts: [],
calls: []
}},
{ '2018-01-01': {
puts: [],
calls: []
}}
]
}
</script>

Something like
const options=dates.options.map(o=>
Object.keys(o).filter(k=>k.match(/^2\d{3}-\d{2}-\d{2}$/))[0]);
The idea is to loop over all options, get all keys for each of the objects and filter out the keys matching the Regexp, which is a date format, starting with 2. From the filtered keys-array I am only interested in the first element ([0]).

for(k in dates) {
keys.push((v=>{
for(let i in v) return i;
})(dates[k]));
}
Try it

Related

JavaScript: How to get all object values of an object without iterator

I convert multidimensional array to object and when I try to return the converted object, I get only the first row values.
Here is my code.
const price = [
[
[1642636800000, 6.479682086929113],
[1642723200000, 6.34357451008912],
[1642809600000, 5.121543485810777],
[1642896000000, 3.9740756848518095],
[1642982400000, 4.3575187509716],
[1643068800000, 3.9012325159931027],
[1643155200000, 3.4317289914580345],
[1643241600000, 3.2757454409610474],
[1643328000000, 2.638504600238906],
[1643414400000, 2.7780564535948247],
[1643500800000, 2.6434238272520734],
[1643587200000, 2.4336766397631195],
[1643673600000, 2.3564650737278945],
[1643760000000, 2.0999935033955395],
[1643846400000, 2.030984947088804],
[1643932800000, 1.9601855774194021],
[1644019200000, 1.939260102893443],
[1644105600000, 1.9099357711674574],
[1644192000000, 1.756137354391081],
[1644278400000, 1.5997203967365643],
[1644364800000, 1.5123161188548575],
[1644451200000, 1.519374648506311],
[1644537600000, 1.537046985055748],
[1644624000000, 1.508372954955599],
[1644710400000, 1.55420714318404],
[1644796800000, 1.5875532111414001],
[1644883200000, 1.6653755421073082],
[1644969600000, 1.6647861014789664],
[1645056000000, 1.7214785428910968],
[1645142400000, 1.7801924052482303],
[1645177320000, 1.7624504335296196],
],
];
code to convert price array to JSON object
const prices = price.map(function (value, key) {
return {
first: value[0][1],
second: value[0][1],
};
});
console.log(prices); //prints only the first rows
How can I get all rows of the object?
Thanks
the problem here is that you have three dimensional array so when you map over it, it will only map over the elements inside first array to do what you want you can try this
price.map(function (item) {
return item.map(function (item) {
return { first: item[0], second: item[1] };
});
})
:)
const prices = price[0].map(function(value, key) {
return {
first: value[0],
second: value[1],
};
});
const pricesArr = [
[
[1642636800000, 6.479682086929113],
[1642723200000, 6.34357451008912],
[1642809600000, 5.121543485810777],
[1642896000000, 3.9740756848518095],
[1642982400000, 4.3575187509716],
[1643068800000, 3.9012325159931027],
[1643155200000, 3.4317289914580345],
[1643241600000, 3.2757454409610474],
[1643328000000, 2.638504600238906],
[1643414400000, 2.7780564535948247],
[1643500800000, 2.6434238272520734],
[1643587200000, 2.4336766397631195],
[1643673600000, 2.3564650737278945],
[1643760000000, 2.0999935033955395],
[1643846400000, 2.030984947088804],
[1643932800000, 1.9601855774194021],
[1644019200000, 1.939260102893443],
[1644105600000, 1.9099357711674574],
[1644192000000, 1.756137354391081],
[1644278400000, 1.5997203967365643],
[1644364800000, 1.5123161188548575],
[1644451200000, 1.519374648506311],
[1644537600000, 1.537046985055748],
[1644624000000, 1.508372954955599],
[1644710400000, 1.55420714318404],
[1644796800000, 1.5875532111414001],
[1644883200000, 1.6653755421073082],
[1644969600000, 1.6647861014789664],
[1645056000000, 1.7214785428910968],
[1645142400000, 1.7801924052482303],
[1645177320000, 1.7624504335296196],
],
];
const prices = pricesArr.flat(1).map(price => ({
first: price[0],
second: price[1]
}));
console.log(prices);
You have a nested array, you can flatten it first and then, iterate to create an array of object.

Split array with condition on element

So I have an array looks like this:
[
{ date: '2021-07-07' },
{ date: '2021-07-07' },
{ date: '2021-07-07' },
{ date: '2021-07-08' },
{ date: '2021-07-09' },
{ date: '2021-07-10' },
{ date: '2021-07-10' }
];
How can I split into 3 array (What I mean is 1 group for unique dates, and another group for duplicate, but if there more than 1 duplicate group, it should separate into another group)
It will looks like this after split
Array 1
[{"date": "2021-07-07"},{"date": "2021-07-07"},{"date": "2021-07-07"}]
Array 2
[{"date": "2021-07-08"},{"date": "2021-07-09"}]
Array 3
[{"date": "2021-07-10"},{"date": "2021-07-10"}]
Below is my code so far, but it only work if the duplicate on have 1
const findDuplicates = arr => {
let sorted_arr = arr.slice().sort();
let result = [];
for (let i = 0; i < sorted_arr.length - 1; i++) {
if (sorted_arr[i + 1].date == sorted_arr[i].date) {
result.push(sorted_arr[i]);
}
}
return result;
};
const filterSame = arr => {
let temp = findDuplicates(arr);
const result = arr.filter(date => date.date == temp[0].date);
return result;
};
const filterUnique = array => {
let result = array.filter(
(e, i) => array.findIndex(a => a['date'] === e['date']) === i
);
let temp = findDuplicates(array);
result = result.filter(function(obj) {
return obj.date !== temp[0].date;
});
return result;
};
You could create a map, keyed by dates, and with as value an empty array. Then populate those arrays. Finally extract the arrays that have more than one element, and add to that result a combined array of those single-element arrays:
function group(data) {
let map = new Map(data.map(o => [o.date, []]));
for (let o of data) map.get(o.date).push(o);
return [
...[...map.values()].filter(({length}) => length > 1),
[...map.values()].filter(({length}) => length == 1).flat()
];
}
let data = [{"date":"2021-07-07"},{"date":"2021-07-07"},{"date":"2021-07-07"},{"date":"2021-07-08"},{"date":"2021-07-09"},{"date":"2021-07-10"},{"date":"2021-07-10"}];
console.log(group(data));
Explanation
let map = new Map(data.map(o => [o.date, []]));
This creates a Map. The constructor is given an array of pairs. For the example data that array looks like this:
[
["2021-07-07", []],
["2021-07-07", []],
["2021-07-07", []],
["2021-07-08", []],
["2021-07-09", []],
["2021-07-10", []],
["2021-07-10", []]
]
The Map constructor will create the corresponding Map, which really removes duplicates. You can imagine it as follows (although it is not a plain object):
{
"2021-07-07": [],
"2021-07-08": [],
"2021-07-09": [],
"2021-07-10": []
}
Then the for loop will populate these (four) arrays, so that the Map will look like this:
{
"2021-07-07": [{date:"2021-07-07"},{date:"2021-07-07"},{date:"2021-07-07"}],
"2021-07-08": [{date:"2021-07-08"}],
"2021-07-09": [{date:"2021-07-09"}],
"2021-07-10": [{date:"2021-07-10"},{date:"2021-07-10"}]
}
In the return statement the Map values are converted to an array twice. Once to filter the entries that have more than 1 element:
[
[{date:"2021-07-07"},{date:"2021-07-07"},{date:"2021-07-07"}],
[{date:"2021-07-10"},{date:"2021-07-10"}]
]
...and a second time to get those that have 1 element:
[
[{date:"2021-07-08"}],
[{date:"2021-07-09"}],
]
The second array is flattened with flat():
[
{date:"2021-07-08"},
{date:"2021-07-09"},
]
The final result concatenates the first array (with duplicate dates) with the flattened array (with unique dates), using the spread syntax (...)
This could be done in a 2 step process
a typical group by operation based on the date properties
aggregating together all the groups which only have 1 result.
const input = [{"date":"2021-07-07"},{"date":"2021-07-07"},{"date":"2021-07-07"},{"date":"2021-07-08"},{"date":"2021-07-09"},{"date":"2021-07-10"},{"date":"2021-07-10"}]
const grouped = input.reduce ( (acc,i) => {
if(!acc[i.date]) acc[i.date] = []
acc[i.date].push(i);
return acc;
},{});
const final = Object.values(Object.entries(grouped).reduce( (acc,[key,values]) => {
if(values.length>1) {
acc[key] = values;
}
else{
if(!acc.others) acc.others = [];
acc.others.push(values[0]);
}
return acc
},{}))
console.log(final);
Note that if you added, for example, 2021-07-11 to your original array, this would get lumped in with all the other "unique" elements. This may or may not be what you expected, but was not clear from the question.
Another option is to sort the array before grouping. If the current date being looped isn't the same as its neighbors, then it doesn't have duplicates.
const input = [{"date":"2021-07-07"},{"date":"2021-07-07"},{"date":"2021-07-07"},{"date":"2021-07-08"},{"date":"2021-07-09"},{"date":"2021-07-10"},{"date":"2021-07-10"}]
input.sort((a,b) => a.date.localeCompare(b.date))
const grouped = input.reduce((acc, o, i, arr) => {
const key = o.date === arr[i-1]?.date || o.date === arr[i+1]?.date
? o.date
: 'lonely'
acc[key] ||= []
acc[key].push(o);
return acc;
}, {});
console.log(Object.values(grouped));

Push nested JSON values to array

I have a JSON array of the following type:
"team": [
{
"paid": {
"refugee": 2018,
"local": 29000,
"international": 12000
}
},
{
"unpaid": {
"refugee": 2019,
"local": 39000,
"international": 19000
}
}
]
I would like to push the values of matching keys into an array, so that I end up with the following new arrays:
var refugees = [2018, 2019]
var local = [29000, 39000]
var international = [12000, 19000]
and so on..
What would be a simple method of doing this? I have succesfully used jQuery in the past for this but need a Javascript only solution:
$.each(team, function (i, v) {
var teams = v;
console.log(teams);
$.each(v, function (i, v) {
refugees.push(v.refugee);
local.push(v.local);
international.push(v.international);
});
});
Try this
var a={"team" : [
{
"paid": {
"refugee": 2018,
"local": 29000,
"international": 12000
}
},
{
"unpaid": {
"refugee": 2019,
"local": 39000,
"international": 19000
}
}
]}
var refugee=[];
var local=[];
var international=[];
a.team.map((e)=>{
if(e.paid)
{
refugee.push(e.paid.refugee);
local.push(e.paid.local);
international.push(e.paid.international)
}
else
{
refugee.push(e.unpaid.refugee);
local.push(e.unpaid.local);
international.push(e.unpaid.international)
}
})
console.log(local)
console.log(international)
console.log(refugee)
You can use reduce.
So here the idea is we are taking a the keys and mapping it to output object. we keep checking if the key is already their in output object we push the value to that particular key and if not we add a new property with value.
let obj = {"team":[{"paid":{"refugee":2018,"local":29000,"international":12000}},{"unpaid":{"refugee":2019,"local":39000,"international":19000}}]}
let op = obj.team.reduce((output,current)=>{
let temp = Object.values(current)[0]
let values = Object.keys(temp)
values.forEach(ele=>{
if(output[ele]){
output[ele].push(temp[ele])
} else {
output[ele] = [temp[ele]]
}
})
return output;
}, {})
console.log(op)
Something like this would work if you wanted a few one-liners:
let local = team.reduce((acc, item) => acc.concat(Object.values(item).map(val => val.local)), []);
let refugee = team.reduce((acc, item) => acc.concat(Object.values(item).map(val => val.refugee)), []);
Use Array#reduce, Object#values, Object#entries, spread syntax, destructuring and Map
const data={"team":[{"paid":{"refugee":2018,"local":29000,"international":12000}},{"unpaid":{"refugee":2019,"local":39000,"international":19000}}]}
const res = data.team.reduce((a,c)=>{
Object.values(c)
.map(Object.entries)
.flat()
.forEach(([k,v])=>{
const arr = a.get(k) || [];
arr.push(v)
a.set(k, arr);
})
return a;
}, new Map())
//get all
console.log([...res.values()]);
//get by type
console.log(res.get('refugee'));
console.log(res.get('local'));
console.log(res.get('international'));

Set First Value as Key in Javascript Array

Creating an array based off selected DataTables Rows
$('#savenlp').click(recordjourney);
function recordjourney() {
var data = table.rows(['.selected']).data().toArray();
console.log( (data) );
console.log( JSON.stringify(data) );
}
data returns
0 : (8) ["Which", "TitleCase", "QuestionWord", "", "", "", "", ""]
JSON.stringify(data) returns
[["baseball","Noun","Singular","","","","",""]]
This information is dynamically generated, so I am just looking to take the first value (in this case baseball) and turn it into something like
"baseball": [
"Noun",
"Singular"
]
I can return the first value (the key I want using)
alert(data[0][0]);
I am much more adept in PHP but I am learning javascript/jquery more and more.
It is my understanding javascript does not have associative arrays, so I am a bit confused as to how to generate this.
const data = [
["baseball","Noun","Singular","","","","",""],
["baseballs","Noun","","Plural","","","","",]
];
const mappedData = data.reduce((acc, row) => { acc[row.shift()] = row.filter(d => d !== ''); return acc; }, {});
console.log(mappedData);
We can use object destructuring and spread operators for ease of use.
In the example below, the key will be the first item and all the rest items will be placed in the newData variable
const data = [["baseball","Noun","Singular","","","","",""]];
const [key, ...newData] = data[0]
// if you want the new data to not have empty entries, simple apply the filter
const newDataFiltered = newData.filter(item => !!item)
const objWithEmpty = {[key]: newData}
const objWithoutEmpty = {[key]: newDataFiltered}
console.log(objWithEmpty, objWithoutEmpty)
For multiple arrays inside the outer array, just enclose the whole logic inside a for loop
const data = [
["baseball","Noun","Singular","","","","",""],
["baseball1","Noun1","Singular1","","","","",""],
["baseball2","Noun2","Singular2","","","","",""]
];
const objWithEmpty = {}
const objWithoutEmpty = {}
data.forEach((array) => {
const [key, ...newData] = array
// if you want the new data to not have empty entries, simple apply the filter
const newDataFiltered = newData.filter(item => !!item)
objWithEmpty[key] = newData
objWithoutEmpty[key] = newDataFiltered
})
console.log(objWithEmpty, objWithoutEmpty)
Simply extract the desired values from data and put them into an object formatted as you like:
const data = [["baseball","Noun","Singular","","","","",""]];
const firstArr = data[0];
const transformedFirstObject = {
[firstArr[0]]: [firstArr[1], firstArr[2]],
};
console.log(transformedFirstObject);
But it's pretty weird to have an object with only one property like that. If your data might have more than one sub-array in it and you want to turn the array of arrays into an array of objects, use map:
const data = [
["baseball","Noun","Singular","","","","",""],
["foo","bar","baz","","","","",""]
];
const transformed = Object.assign(...data.map(([prop, value1, value2]) => ({ [prop]: [value1, value2] })));
console.log(transformed);
A bit simpler compared to other answers here but works as well.
const data = [
["baseball","Noun","Singular","","","","",""],
["baseball1","Noun1","Singular1","","","","",""],
["baseball2","Noun2","Singular2","","","","",""]
];
const obj = [];
data.forEach(function(i) {
let jsonObj = {};
jsonObj [i[0]] = i.slice(1).filter(x=>x !='');
obj.push(jsonObj)
});
console.log(JSON.stringify(obj))
Just using forEach, considering multiple array elements.
var obj = {};
var arr = [
["baseball", "Noun", "Singular", "", "", "", "", ""],
["Test", "Test1", "Test2", "", "", "", "", ""]
];
arr.forEach(function(val, idx) {
val.forEach(function(val1, idx1) {
if (idx1 === 0) {
obj[val1] = val.slice(1, val.length)
}
})
})
console.log(JSON.stringify(obj))

Firebase orderByChild Ignored

How do I sort the following structure in Firebase by sortOrder?
categories {
{
"b": {
"name": "Banana",
"sortOrder": 2
},
"a": {
"name": "Apple",
"sortOrder": 1
}
}
}
From the documentation it looks as simple as:
ref('categories').orderByChild('sortOrder').once('value') ...
However, the first node returned is banana. It doesn't matter what string value I use. For example, the following returns the same results:
ref('categories').orderByChild('xxx').once('value') ...
Full function:
public list(): Observable<Category[]> {
let ref = firebase.database().ref('categories').orderByChild('sortOrder');
return Observable.fromPromise(<Promise<any>>ref.once('value'))
.flatMap(snapshot => {
let objects = snapshot.val();
let categories: Array<Category> = new Array();
for (let key in objects) {
let category: Category = objects[key];
category.code = key;
categories.push(category);
}
return Observable.of(categories);
}
);
}
The problem is that when you access the children via the snapshot's value's keys, the order is indeterminate.
You need to use the snapshot's forEach method:
return Observable.fromPromise(<Promise<any>>ref.once('value'))
.flatMap(snapshot => {
let categories: Array<Category> = new Array();
snapshot.forEach(childSnapshot => {
let category: Category = childSnapshot.val();
category.code = childSnapshot.key;
categories.push(category);
});
return Observable.of(categories);
}
);
Also, you could just use map and return categories.

Categories

Resources