How to get key values from nested JSON? - javascript

I have this JSON:
var json = [{'range':'2012','subtotal':'116.0','total_tax':'11.6','total':'127.6'},{'range':'2013','subtotal':'936.0','total_tax':'93.6','total':'1029.6'},{'range':'2014','subtotal':'368.0','total_tax':'36.8','total':'404.8'},{'range':'2015','subtotal':'267.0','total_tax':'26.7','total':'293.7'}];
How can I convert this into an array of ranges like this (using Javascript or jQuery):
['2012', '2013', '2014', '2015']
Thanks for any help.

You could simply use .map:
json.map(function(i) {
return i.range;
});
//["2012", "2013", "2014", "2015"]

First, that's not JSON, that's a JavaScript object literal. I'll refer to your data as data instead of json.
Second, let's use two reusable functions to express our intent more clearly
let map = f => x => x.map(f);
let prop = y => x => x[y];
Now, we simply map over your data and extract the property we want
map(prop('range'))(data);
// => ["2012","2013","2014","2015"]
Or we can define a reusable helper
let getRange = map(prop('range'));
getRange(data);
// => ["2012","2013","2014","2015"]
Here's the ES5 equivalent
var map = function map(f) {
return function (x) {
return x.map(f);
};
};
var prop = function prop(y) {
return function (x) {
return x[y];
};
};
var getRange = map(prop('range'));
getRange(data);
// => ["2012","2013","2014","2015"]

var mapped = json.map(function(obj) {
return obj.range;
});
Also, minor point; what you have is an array. JSON is when an array/object is represented as a string (which happens to match the JavaScript literal notation of it)

You actually have an array of nested objects. Here are some options:
The naive solution would be to iterate over this array and push to a new array the values you want:
function getRange(arr) {
var result = [];
for (var i = 0; i < arr.length; i++) {
result.push(arr[i].range)
};
return result;
}
You can also use the native Array.map method to do this easier:
function getRange(arr) {
return arr.map(function(elem) {
return i.range;
})
}

Related

Oh man groupBy() and arrayToObject() are breaking me

So I have been working on some extra credit for my classes. I am very new to programming and have already sought help for this same assignment, I started rolling through and now am absolutely lost.
I need to define the two functions groupBy() and arrayToObect() as asked in the below test.
I'm not necessarily looking for the answer but if someone could help point me in the right direction that would be awesome.
What I have deduced is as follows:
I need to be using the spread operator ...
I need to create a newObj = {}
a. and somehow push the element derived from the array into the obj
I need to take the individual values of the array and assign them as keys, with the variances as the properties of the key.
Bracket notation
I have been racking my brain for hours on this now and could really use some guidance!
describe('groupBy', function () {
const input = [4.2, 6.1, 6.3]
const result = groupBy(input, (el) => Math.floor(el))
it('returns an object', function () {
expect(result).to.be.an('object')
})
it('group array items together based on the callback return value', function () {
expect(result).to.be.eql({
4: [4.2],
6: [6.1, 6.3],
})
})
})
describe('arrayToObject', function () {
const input = ['cat', 'dog', 'bird']
const result = arrayToObject(input, (word) => word + 's')
it('returns an object', function () {
expect(result).to.be.an('object')
})
it('object has original array elements as keys and the result of the callback as values', function () {
expect(result).to.be.eql({
cat: 'cats',
dog: 'dogs',
bird: 'birds',
})
})
})
})
groupBy
Write a function called groupBy which takes an array and a callback. The function should return an object. Each return value of the callback should be a key of the object and the values should be the input element with which the callback was called.
arrayToObject
Write a function called arrayToObject which takes an array and a callback. The function should return an object. Each element of the input array should be a key of the returned object and the output from the callback with an element passed in as the corresponding value.
These questions have been answered a million times on stackoverflow. Essentially what you want to be doing here is using the common js array functions map, filter, reduce, flatten, ..., and think about how your problem can be expressed in terms of those.
A lot of real world code is transforming data like this, so it's good to be comfortable doing it.
Also realize that spread syntax copies the entire object which can be pretty inefficient. JavaScript doesn't have persistent data structures! It's usually better to just mutate — as long as your code is what "owns" the object.
const groupBy = (elts, keyfn) =>
elts.reduce((m, elt) => {
const key = keyfn(elt);
m[key] = m[key] || [];
m[key].push(elt);
return m;
}, {});
const arrayToObject = (elts, fn) =>
elts.reduce(
(obj, elt) => Object.assign(obj, { [elt]: fn(elt) }),
{},
);
I figured it out using a for loop!!
function groupBy(arr, callback) {
const newObj = {}
for (let i = 0; i < arr.length; i++) {
if (callback(arr[i])) {
const key = callback(arr[i])
newObj[key] = newObj[key] || []
newObj[key].push(arr[i])
}
}
return newObj
}
function arrayToObject(arr, callback) {
const obj = {}
for (let i = 0; i < arr.length; i++) {
if (callback(arr[i])) {
const key = callback(arr[i])
obj[arr[i]] = obj[key] || callback(arr[i])
}
}
return obj
}

JavaScript: Extract values of a specific key out of key-value array and store them in a new array

I have an' multidimensional key-value array like this:
'[[
{"_time":"2022-01-03T00:00:00Z","_value":10.70140000000014,"ts":1641168000000},
{"_time":"2022-01-04T00:00:00Z","_value":13.002499999999767,"ts":1641254400000},
{"_time":"2022-01-05T00:00:00Z","_value":16.171700000000182,"ts":1641340800000},
{"_time":"2022-01-06T00:00:00Z","_value":17.48929999999981,"ts":1641427200000},
]]'
and I need the values from each of them in a new variable in this way:
[10.70140000000014,13.002499999999767,16.171700000000182,17.48929999999981]
I tried it with map but that do not match my needs:
function getPreparedData(data) {
if (data) {
return data[0].map(elm => ({
a: elm._value
}));
}
return [];
};
How can I solve this?
Thanks
Frank
In your example, the function getPreparedData is returning array of objects. You actually want to return an array of values (where values are just the value of the _value property)
const data = [[
{"_time":"2022-01-03T00:00:00Z","_value":10.70140000000014,"ts":1641168000000},
{"_time":"2022-01-04T00:00:00Z","_value":13.002499999999767,"ts":1641254400000},
{"_time":"2022-01-05T00:00:00Z","_value":16.171700000000182,"ts":1641340800000},
{"_time":"2022-01-06T00:00:00Z","_value":17.48929999999981,"ts":1641427200000},
]];
function getPreparedData(data) {
return data[0].map(elm => elm._value)
};
const res = getPreparedData(data);
console.log(res);

ES6 Filtering objects by unique attribute

I've an array of errors, each error has a non-unique param attribute.
I'd like to filter the array based on whether the param has been seen before.
Something like this:
const filteredErrors = [];
let params = [];
for(let x = 0; x < errors.length; x++) {
if(!params.includes(errors[x].param)) {
params.push(errors[x].param);
filteredErrors.push(errors[x]);
}
}
But I've no idea how to do this in ES6.
I can get the unique params const filteredParams = Array.from(new Set(errors.map(error => error.param)));
but not the objects themselves.
Pretty sure this is just a weakness in my understanding of higher order functions, but I just can't grasp it
You could destrucure param, check against params and add the value to params and return true for getting the object as filtering result.
As result you get an array of first found errors of the same type.
const
params = [],
filteredErrors = errors.filter(({ param }) =>
!params.includes(param) && params.push(param));
Instead of an array you can make use of an object to keep a map of existing values and make use of filter function
let params = {};
const filteredErrors = errors.filter(error => {
if(params[error.param]) return false;
params[error.param] = true;
return true;
});
i'd probably do it like this with a reduce and no need for outside parameters:
const filteredErrors = Object.values(
errors.reduce((acc, val) => {
if (!acc[val.param]) {
acc[val.param] = val;
}
return acc;
}, {}))
basically convert it into an object keyed by the param with the object as values, only setting the key if it hasn't been set before, then back into an array of the values.
generalized like so
function uniqueBy(array, prop) {
return Object.values(
array.reduce((acc, val) => {
if (!acc[val[prop]]) {
acc[val[prop]] = val;
}
return acc;
}, {}))
}
then just do:
const filteredErrors = uniqueBy(errors, 'param');
If your param has a flag identifier if this param has been seen before then you can simply do this.
const filteredErrors = errors.filter(({ param }) => param.seen === true);
OR
const filteredErrors = errors.filter((error) => error.param.seen);
errors should be an array of objects.
where param is one of the fields of the element of array errors and seen is one of the fields of param object.
You can do it by using Array.prototype.reduce. You need to iterate through the objects in the array and keep the found params in a Set if it is not already there.
The Set.prototype.has will let you find that out. If it is not present in the Set you add it both in the Set instance and the final accumulated array, so that in the next iteration if the param is present in your Set you don't include that object:
const errors = [{param: 1, val: "err1"}, {param: 2, val: "err2"}, {param: 3, val: "err3"}, {param: 2, val: "err4"}, {param: 1, val: "err5"}];
const { filteredParams } = errors.reduce((acc, e) => {
!acc.foundParams.has(e.param) && (acc.foundParams.add(e.param) &&
acc.filteredParams.push(e));
return acc;
}, {foundParams: new Set(), filteredParams: []});
console.log(filteredParams);

How to convert Javascript Array to array of functions?

I had a question in my interview where they asked me to transform an array to array of functions like below:
var a = ["a", 24, { foo: "bar" }];
var b = transform(a);
console.log(a[1]); // 24
console.log(b[1]()); // 24
I tried many combinations but I couldn't really do what they ask. Can someone tell me how to implement the transform function?
I'm not exactly sure about their intention, but a simple approach to provide the given results would be as follows:
function transform(a){
return a.map( (el) => () => el );
}
PS: the interesting follow up question would then be about the differences between the results for b[0]() and b[1]() compared to b[2]() and how to mitigate the problems that might arise for the later.
The desired behavior is a bit weird but you can do as follow:
const transform = arr => arr.map(elmt => () => elmt)
You can use a nice feature here, Proxy...
var arr = ["a", 24, { foo: "bar" }];
function transform(arr){
return new Proxy(arr, {
get: (obj, prop) => { return ()=>obj[prop] }
});
}
var newArr = transform(arr);
newArr[0]();
One approach you could take is to call Array.prototype.map method on your original array a - the map method will return a new array. Each index of the new array will have get a value of an anonymous function definition that, when called, will return the value of the corresponding index in the original array.
var a = ["a", 24, {
foo: "bar"
}];
var b = transform(a);
console.log(a[1]); // 24
console.log(b[1]()); // 24
function transform(array) {
return array.map(function(el) {
return function() {
return el;
}
});
}

JavaScript - Filter <key,value> Object by key

I am looking for a short and efficient way to filter objects by key, I have this kind of data-structure:
{"Key1":[obj1,obj2,obj3], "Key2":[obj4,obj5,obj6]}
Now I want to filter by keys, for example by "Key1":
{"Key1":[obj1,obj2,obj3]}
var object = {"Key1":[1,2,3], "Key2":[4,5,6]};
var key1 = object["Key1"];
console.log(key1);
you can use the .filter js function for filter values inside an object
var keys = {"Key1":[obj1,obj2,obj3], "Key2":[obj4,obj5,obj6]};
var objectToFind;
var keyToSearch = keys.filter(function(objects) {
return objects === objectToFind
});
The keyToSearch is an array with all the objects filter by the objectToFind variable.
Remember, in the line return objects === objectToFind is where you have to should your statement. I hope it can help you.
You can create a new object based on some custom filter criteria by using a combination of Object.keys and the array .reduce method. Note this only works in es6:
var myObject = {"Key1":["a","b","c"], "Key2":["e","f","g"]}
function filterObjectByKey(obj, filterFunc) {
return Object.keys(obj).reduce((newObj, key) => {
if (filterFunc(key)) {
newObj[key] = obj[key];
}
return newObj;
}, {});
}
const filteredObj = filterObjectByKey(myObject, x => x === "Key1")
console.log(filteredObj)
Not sure what exactly are you trying to achieve, but if you want to have a set of keys that you would like to get the data for, you have quite a few options, one is:
var keys = ['alpha', 'bravo'];
var objectToFilterOn = {
alpha: 'a',
bravo: 'b',
charlie: 'c'
};
keys.forEach(function(key) {
console.log(objectToFilterOn[key]);
});

Categories