Maximum value from the JSON - javascript

I needed the maximum value from the particular JSON object. I needed it to make a scale for apple and banana's for d3 from its maximum value
So how do I get the maximum value of apple and banana from this JSON. I don't need the month name. I don't want to use any for or while loops.
var arr = [
{
"date":"Jan",
"values": [
{"name":"apple","value":100},
{"name":"banana","value":200}
]
},
{
"date":"Feb",
"values": [
{"name":"apple","value":300},
{"name":"banana","value":455}
]
},
{
"date":"Mar",
"values": [
{"name":"apple","value":588},
{"name":"banana","value":700}
]
}
];

You can also use Math.max after finding the fruit from values with find:
var arr = [{
"date": "Jan",
"values": [{
"name": "apple",
"value": 100
},
{
"name": "banana",
"value": 200
}
]
},
{
"date": "Feb",
"values": [{
"name": "apple",
"value": 300
},
{
"name": "banana",
"value": 455
}
]
},
{
"date": "Mar",
"values": [{
"name": "apple",
"value": 588
},
{
"name": "banana",
"value": 700
}
]
}
];
const maxVal = (fruit) => Math.max(...arr.map(d => d.values.find(v => v.name === fruit).value));
console.log(maxVal('apple'));
console.log(maxVal('banana'));

You could something like this:
const max = (list) => list.reduce((acc, cur) => {
let apple = cur.values[0].name === 'apple' ? cur.values[0] : cur.values[1];
let banana = cur.values[0].name === 'banana' ? cur.values[0] : cur.values[1];
acc[0] = acc[0] < apple.value ? apple.value : acc[0];
acc[1] = acc[1] < banana.value ? banana.value : acc[1];
return acc;
}, [0, 0]);
It returns an array, the first item is the max number of apples, the second is the max number of bananas.
Example
var arr = [{
"date": "Jan",
"values": [{
"name": "apple",
"value": 100
},
{
"name": "banana",
"value": 200
}
]
},
{
"date": "Feb",
"values": [{
"name": "apple",
"value": 300
},
{
"name": "banana",
"value": 455
}
]
},
{
"date": "Mar",
"values": [{
"name": "apple",
"value": 588
},
{
"name": "banana",
"value": 700
}
]
}
];
const max = (list) => list.reduce((acc, cur) => {
let apple = cur.values[0].name === 'apple' ? cur.values[0] : cur.values[1];
let banana = cur.values[0].name === 'banana' ? cur.values[0] : cur.values[1];
acc[0] = acc[0] < apple.value ? apple.value : acc[0];
acc[1] = acc[1] < banana.value ? banana.value : acc[1];
return acc;
}, [0, 0]);
console.log(
max(arr)
);

Related

Merge arrays matching a particular key value in JavaScript

I have an array which is like this:
var arr = [{
"date": "JAN",
"value": 5,
"weight": 3
}, {
"date": "JAN",
"value": 4,
"weight": 23
}, {
"date": "FEB",
"value": 9,
"weight": 1
}, {
"date": "FEB",
"value": 10,
"weight": 30
}]
I want to match the primary key which is heredate. Matching this I want to merge the rest of the key values and get this following output:
[{
"date": "JAN",
"value": [5, 4],
"weight": [3, 23]
}, {
"date": "FEB",
"value": [9, 10],
"weight": [1, 30]
}]
I have written a function like this but can't figure out how to concat the key values:
var arr = [{
"date": "JAN",
"value": 5,
"weight": 3
}, {
"date": "JAN",
"value": 4,
"weight": 23
}, {
"date": "FEB",
"value": 9,
"weight": 1
}, {
"date": "FEB",
"value": 10,
"weight": 30
}]
const transform = (arr, primaryKey) => {
var newValue = [];
for (let i = 0; i < arr.length; i++) {
for (let j = 1; j < arr.length; j++) {
if (primaryKey[i] === primaryKey[j]) {
newValue.push({
...arr[i],
...arr[j]
});
}
}
}
return newValue
};
console.log(transform(arr,'date'))
Using Array#reduce, iterate over the list while updating a Map where the key is the primary-key and the value is the grouped object. In every iteration, create/update the pair.
Using Map#values, return the list of grouped objects
const transform = (arr, primaryKey) => [...
arr.reduce((map, { [primaryKey]: key, ...e }) => {
const { [primaryKey]: k, ...props } = map.get(key) ?? {};
for(let prop in e) {
props[prop] = [...(props[prop] ?? []), e[prop]];
}
map.set(key, { [primaryKey]: key, ...props });
return map;
}, new Map)
.values()
];
const arr = [ { "date": "JAN", "value": 5, "weight": 3 }, { "date": "JAN", "value": 4, "weight": 23 }, { "date": "FEB", "value": 9, "weight": 1 }, { "date": "FEB", "value": 10, "weight": 30 } ];
console.log( transform(arr, 'date') );
The following code should work:
const transform = (arr, primaryKey) => {
var newValue = [];
for(let i = 0; i < arr.length; i++){
arr[i]["value"] = [arr[i]["value"]];
arr[i]["weight"] = [arr[i]["weight"]];
}
newValue.push(arr[0])
for(let i = 1; i < arr.length; i++){
let contains = false;
for(let j = 0; j < newValue.length; j++){
if(newValue[j][primaryKey] == arr[i][primaryKey]){
newValue[j]["value"].push(arr[i]["value"][0]);
newValue[j]["weight"].push(arr[i]["weight"][0]);
contains = true;
}
}
if(!contains){
newValue.push(arr[i]);
}
}
return newValue
};
var arr = [{
"date": "JAN",
"value": 5,
"weight": 3
}, {
"date": "JAN",
"value": 4,
"weight": 23
}, {
"date": "FEB",
"value": 9,
"weight": 1
}, {
"date": "FEB",
"value": 10,
"weight": 30
}]
var newthing = transform(arr,"date");
console.log(newthing);
Output:
[ { date: 'JAN', value: [ 5, 4 ], weight: [ 3, 23 ] },
{ date: 'FEB', value: [ 9, 10 ], weight: [ 1, 30 ] } ]
The way this code works is that first, we turn the values of the keys for "value" and "weight" into lists.
Then, we begin by pushing the first element of arr into newValue.
From here, we do a nested for loop to iterate through the remaining of arr and newValue:
If the value of "date" for every element of arr already exists in newValue, then we will push in the values of "value" and "weight" that belongs to arr.
However, if it does not exist, then we will simply push that element inside of newValue.
I hope this helped answer your question! Pleas let me know if you need any further help or clarification :)
Combining a couple of reduce can also do the same job:
const arr = [{
"date": "JAN",
"value": 5,
"weight": 3
}, {
"date": "JAN",
"value": 4,
"weight": 23
}, {
"date": "FEB",
"value": 9,
"weight": 1
}, {
"date": "FEB",
"value": 10,
"weight": 30
}]
const arrayMappedByDate = arr.reduce((acc, curData) => {
if (acc[curData.date]) {
acc[curData.date].push(curData)
} else {
acc[curData.date] = [curData]
}
return acc
}, {})
const transformedArray = Object.entries(arrayMappedByDate).map(([dateInit, data]) => {
const normalized = data.reduce((acc, cur) => {
if (acc.date) {
acc.value.push(cur.value)
acc.weight.push(cur.weight)
} else {
acc = {
date: cur.date,
value: [cur.value],
weight: [cur.weight]
}
}
return acc
}, {})
return { [dateInit]: normalized }
})
console.log(transformedArray)

filter nested array with Javascript

having an array with objects and inside an options array how do I filter the inner array of objects by key value?
Here is the following example:
let test = [{
"options": [{
"label": "Audi",
"value": 10
},
{
"label": "BMW",
"value": 18
},
{
"label": "Mercedes Benz",
"value": 116
},
{
"label": "VW",
"value": 184
}
],
"label": "test1"
},
{
"options": [{
"label": "Adler",
"value": 3664
},
{
"label": "Alfa Romeo",
"value": 3
},
{
"label": "Alpine",
"value": 4
}
],
"label": "test2"
}
]
how do I get back the object:
{
"label": "Audi",
"value": 10
}
if I filter with keyword Audi
return label.toLowerCase().includes(inputValue.toLowerCase());
I tried with the following
test.map((k) => {
res = k.options.filter((j) => {
inputValue.toLowerCase();
if (j.label.toLowerCase().includes(inputValue.toLowerCase())) {
return j;
}
});
});
You need to return the result of filter(), not just assign it to a variable, so that map() will return the results.
let test = [{
"options": [{
"label": "Audi",
"value": 10
},
{
"label": "BMW",
"value": 18
},
{
"label": "Mercedes Benz",
"value": 116
},
{
"label": "VW",
"value": 184
}
],
"label": "test1"
},
{
"options": [{
"label": "Adler",
"value": 3664
},
{
"label": "Alfa Romeo",
"value": 3
},
{
"label": "Alpine",
"value": 4
}
],
"label": "test2"
}
]
let inputValue = "audi";
let search = inputValue.toLowerCase();
let result = test.map(k => k.options.filter(j => j.label.toLowerCase().includes(search)));
console.log(result);
This will return all options matching the search query :
function find(array, query) {
return array.reduce((prev, current) => prev.concat(current.options), []).filter(item => item.label.includes(query))
}
find(test, 'Audi')
Use flatMap() followed by filter():
let test=[{options:[{label:"Audi",value:10},{label:"BMW",value:18},{label:"Mercedes Benz",value:116},{label:"VW",value:184}],label:"test1"},{options:[{label:"Adler",value:3664},{label:"Alfa Romeo",value:3},{label:"Alpine",value:4}],label:"test2"}]
let result = test.flatMap(el => {
return el.options.filter(car => car.label == "Audi")
})[0]
console.log(result)
You need to go two levels deep when traversing your array.
function filterArray(needle, haystack) {
return haystack
.map(h => h.options)
.flatMap(h => h )
.filter(h => h.label.toLowerCase().includes(needle.toLowerCase()));
CodeSandbox
This might gile your answer:
console.log(test[0].options[0]);

How to sum the values of one property name based on sharing the value of another property name in an array of objects (in Javascript)

I have an array of hundreds of objects structured like:
[
{
"type": "apples",
"count": 10
},
{
"type": "oranges",
"count": 20
},
{
"type": "apples",
"count": 5
},
{
"type": "grapes",
"count": 20
},
{
"type": "grapes",
"count": 10
}
]
I need to loop through them and create a new array combining the counts if they share the same type. So output from above example would need to be:
[
{
"type": "apples",
"count": 15
},
{
"type": "oranges",
"count": 20
},
{
"type": "grapes",
"count": 30
},
]
Any help would be greatly appreciated.
I would use reduce. Note that this solution uses ES6 syntax.
let values = [
{
"type": "apples",
"count": 10
},
{
"type": "oranges",
"count": 20
},
{
"type": "apples",
"count": 5
},
{
"type": "grapes",
"count": 20
},
{
"type": "grapes",
"count": 10
}
]
let collatedValues = values.reduce((accumulator, currentValue) => {
let existing = accumulator.find(n => n.type === currentValue.type);
if (existing) {
existing.count += currentValue.count
} else {
accumulator.push(currentValue)
}
return accumulator
},[])
console.log(collatedValues)
How about:
const data = [
{
type: 'apples',
count: 10
},
{
type: 'oranges',
count: 20
},
{
type: 'apples',
count: 5
},
{
type: 'grapes',
count: 20
},
{
type: 'grapes',
count: 10
}
];
const types = data.map((food) => food.type);
const uniqueTypes = [...new Set(types)];
const counts = uniqueTypes.map((foodType) => ({
type: foodType,
count: data
.filter((food) => food.type === foodType)
.map((food) => food.count)
.reduce((acc, currCount) => acc + currCount, 0)
}));

Dynamically create array of objects from the object with the array values

Currently I have the below object structure,
`let selectedOptions = {
"color": {
"id": "2",
"values": [
{
"value": "red",
"label": "Red",
"id": 1
},
{
"value": "blue",
"label": "Blue",
"id": 2
}
]
},
"size": {
"id": "19",
"values": [
{
"value": "medium",
"label": "Medium",
"id": 2
}
]
},
"demo": {
"id": "19",
"values": [
{
"value": "neylon",
"label": "Neylon",
"id": 2
}
]
}
.
.
.
N
}; `
And want to create array of objects from the above object like as below,
[
{ color: "red", size: "medium", demo: "neylon" },
{ color: "blue", size: "medium", demo: "neylon" }
]
I have tried like below but it didn't worked
https://jsfiddle.net/6Lvb12e5/18/
let cArr = [];
for(key in selectedOptions) {
selectedOptions[key].values.forEach(function(val,i) {
cArr.push({ [key]: val.value })
})
}
Thanks
You could take the wanted parts, like color, size and demo and build a cartesian product out of the given data.
const
cartesian = (a, b) => a.reduce((r, v) => r.concat(b.map(w => [].concat(v, w))), []),
options = { color: { id: "2", values: [{ value: "red", label: "Red", id: 1 }, { value: "blue", label: "Blue", id: 2 }] }, size: { id: "19", values: [{ value: "small", label: "Small", id: 1 }, { value: "medium", label: "Medium", id: 2 }] }, demo: { id: "19", values: [{ value: "neylon", label: "Neylon", id: 2 }] } },
parts = Object
.entries(options)
.map(([k, { values }]) => [k, values.map(({ value }) => value)]),
keys = parts.map(([key]) => key),
result = parts
.map(([, values]) => values)
.reduce(cartesian)
.map(a => Object.assign(...a.map((v, i) => ({ [keys[i]]: v }))));
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
I am not sure that is this the best way to do this, and even the data is missing but as a comment, it is quite big to post but can try:
let selectedOptions = {
"color": {
"id": "2",
"values": [
{
"value": "red",
"label": "Red",
"id": 1
},
{
"value": "blue",
"label": "Blue",
"id": 2
}
]
},
"size": {
"id": "19",
"values": [
{
"value": "medium",
"label": "Medium",
"id": 2
}
]
},
"demo": {
"id": "19",
"values": [
{
"value": "neylon",
"label": "Neylon",
"id": 2
}
]
}
};
let cArr = [];
var obj = {};
var glob;
for(key in selectedOptions) {
selectedOptions[key].values.forEach(function(val,i) {
obj[key] = val.value;
}
)
glob = obj;
}
cArr.push(glob);
console.log(cArr)

Build nested object arrays within recursive function

As per my original question geared specifically for React (React recursive tree pass JSON path), I have realised the problem is pretty generic.
I have a recursive function that essentially loops through a treelike JSON structure, each time it outputs a branch I want to pass an object of the structures location in the tree like below.. Is there a simpler way to pass the structure? Is the data structure poor / should each chid have a unique ID attached?
My JSON object is below so you can see what I'm working with.
Any help much appreciated!
Level 1 child
{value: "Fruit"}
Level 2 child
{value: "Fruit", nested_values: [{ value: 'Tropical'}] }
Level 3 child
{value: "Fruit", nested_values: [{ value: 'Tropical', nested_values:[{ value: 'Pineapple' }]}] }
Code - kind of works, but then I get all values within the same nested_values array
const createSelectionHierarchy = (data, isSub, level = 2, hierarchy = {}) => {
let children = [];
if (isSub) { level++; }
let obj = {};
obj.name = cat;
const cat = hierarchy.value;
for (let i in data) {
const subcat = data[i].value;
if (typeof(data[i].nested_values) === 'object') { // Sub array found, build structure
obj.values = subcat;
obj.nested_values = [];
hierarchy.nested_values.push(obj);
children.push(
<FilterItem key={i} data={data[i]} hierarchy={hierarchy} level={level}>
{createSelectionHierarchy(data[i].nested_values, true, level, hierarchy)}
</FilterItem>
);
} else { // No sub array, bottom of current branch
children.push(
<p className="filter-item level-last" key={i}>
{data[i].value}
</p>);
}
}
return children;
}
JSON
{
"value": "Fruit",
"occurrence_count": 5,
"nested_values": [{
"value": "Berries",
"occurrence_count": 3,
"nested_values": [{
"value": "Strawberry",
"occurrence_count": 1
}, {
"value": "Blackberry",
"occurrence_count": 1
}, {
"value": "Raspberry",
"occurrence_count": 1
}, {
"value": "Redcurrant",
"occurrence_count": 1
}, {
"value": "Blackcurrant",
"occurrence_count": 1
}, {
"value": "Gooseberry",
"occurrence_count": 1
}, {
"value": "Cranberry",
"occurrence_count": 1
}, {
"value": "Whitecurrant",
"occurrence_count": 1
}, {
"value": "Loganberry",
"occurrence_count": 1
}, {
"value": "Strawberry",
"occurrence_count": 1
}]
}, {
"value": "Tropical",
"occurrence_count": 2,
"nested_values": [{
"value": "Pineapple",
"occurrence_count": 1
}, {
"value": "Mango",
"occurrence_count": 1
}, {
"value": "Guava",
"occurrence_count": 1
}, {
"value": "Passion Fruit",
"occurrence_count": 1
}, {
"value": "Dragon Fruit",
"occurrence_count": 1
}]
}]
}
Desired output
<FilterItem ...... hierarchy={{value: "Fruit"}}>
<FilterItem ...... hierarchy={{value: "Fruit", nested_values: [{ value: 'Tropical'}] }}>
<FilterItem ...... hierarchy={{value: "Fruit", nested_values: [{ value: 'Tropical', nested_values:[{ value: 'Pineapple' }]}] }}>
</FilterItem>
</FilterItem>
</FilterItem>
For each branch (level of tree), this function will extract the value and then call itself on each of its children, if there are any, and store their return values in an array.
function convert(branch) {
const hierarchy = {
value: branch.value
};
if (branch.nested_values !== undefined)
hierarchy.nested_values = branch.nested_values.map(subranch => convert(subranch))
return hierarchy;
}
const input = {
"value": "Fruit",
"occurrence_count": 5,
"nested_values": [{
"value": "Berries",
"occurrence_count": 3,
"nested_values": [{
"value": "Strawberry",
"occurrence_count": 1
}, {
"value": "Blackberry",
"occurrence_count": 1
}, {
"value": "Raspberry",
"occurrence_count": 1
}, {
"value": "Redcurrant",
"occurrence_count": 1
}, {
"value": "Blackcurrant",
"occurrence_count": 1
}, {
"value": "Gooseberry",
"occurrence_count": 1
}, {
"value": "Cranberry",
"occurrence_count": 1
}, {
"value": "Whitecurrant",
"occurrence_count": 1
}, {
"value": "Loganberry",
"occurrence_count": 1
}, {
"value": "Strawberry",
"occurrence_count": 1
}]
}, {
"value": "Tropical",
"occurrence_count": 2,
"nested_values": [{
"value": "Pineapple",
"occurrence_count": 1
}, {
"value": "Mango",
"occurrence_count": 1
}, {
"value": "Guava",
"occurrence_count": 1
}, {
"value": "Passion Fruit",
"occurrence_count": 1
}, {
"value": "Dragon Fruit",
"occurrence_count": 1
}]
}]
};
function convert(branch) {
const hierarchy = {
value: branch.value
};
if (branch.nested_values !== undefined)
hierarchy.nested_values = branch.nested_values.map(subranch => convert(subranch))
return hierarchy;
}
console.log(convert(input));
On a side note, what you supplied is not valid JSON (keys mustn't have quotes), it is a JavaScript object. To get an object from a JSON string, you have to call JSON.parse().

Categories

Resources