How can I get the last items from a nested array? - javascript

I was struggling to get the last object item from a nested array. I tried to implement flatMap, flat, filter, and splice. However, I can not still get the expected array.
const array = [
[
{
total_cases: 18,
},
{
total_cases: 32,
},
{
total_cases: 7,
},
],
[
{
total_cases: 4,
},
{
total_cases: 52,
},
],
[
{
total_cases: 68,
},
],
];
I have an array like the above. How can I get only the last-object item into a new array?
Expected new array should be like this:
[7, 52, 68]
Thanks in advance!

You can use .at() method. Negative parametr count back from the last item in the array. So .at(-1) return the last array's element.
const array=[[{total_cases:18},{total_cases:32},{total_cases:7}],[{total_cases:4},{total_cases:52}],[{total_cases:68}]];
const result = array.map(e => e.at(-1).total_cases);
console.log(...result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Edit based on changes to question.
You can use map and slice to select only the last element of each nested array, then flat to flatten the array and map again to select the total_cases values:
const array = [
[
{ total_cases: 18 },
{ total_cases: 32 },
{ total_cases: 7 },
],
[
{ total_cases: 4 },
{ total_cases: 52 },
],
[
{ total_cases: 68 },
],
];
const result = array
.map(a => a.slice(a.length - 1))
.flat(1)
.map(o => o.total_cases)
console.log(result)
Original Answer
You can flatten the array, filter it based on the date value and then use map to extract the total_cases values:
const array = [
[
{
date: "2020-02-25",
total_cases: 18,
},
{
date: "2020-02-26",
total_cases: 32,
},
{
date: "last-object",
total_cases: 7,
},
],
[
{
date: "2020-02-26",
total_cases: 4,
},
{
date: "last-object",
total_cases: 52,
},
],
[
{
date: "last-object",
total_cases: 68,
},
],
];
const result = array
.flat(1)
.filter(o => o.date == 'last-object')
.map(o => o.total_cases)
console.log(result)

Related

How find max of an inner element in a list of key, values?

I have a list of items as you see below. The values for each year key is a list of 10 items but to make it short, I am only showing the first couple of them. How I can find the maximum of all inner "count" values? I have looked at various approaches but none has worked so far and perhaps I am missing something here. For instance, I really like some of one liners here but they didnt work for me enter link description here
Just to clarify that data is the result of a nest on csv file and it meant to be used in d3 chart and preferably no import library other than standard ones.
data = [
{'2015': values: [{key: '0', value: {count: 45}},{key: '1', value: {count: 3}}, ... ]},
{'2016': values: [{key: '0', value: {count: 67}},{key: '1', value: {count: 0}}, ... ]},
{'2017': values: [{key: '0', value: {count: 12}},{key: '1', value: {count: 8}}, ... ]}
]
To better show how data looks like, here is the screen shot in case it helps clarification of the question.
You could destructure the object like this by flattening the values array and then mapping to get the count variable.
var data = [
{"key":"2015", "values": [{"key": 0, "value": {"count": 45}},{"key": 1, "value": {"count": 3}}]},{"key":"2016", "values": [{"key": 0, "value": {"count": 67}},{"key": 1, "value": {"count": 0}}]},{"key": "2017", "values": [{"key": 0, "value": {"count": 12}},{"key": 1, "value": {"count": 8}}]}
]
var num = Math.max(... data.map(d=>d.values).flat().map(v=>v.value.count))
console.log(num)
Something like this should work
const myData = [
{ key: "2015", values: [10, 5, 4, 3, 2, 1, 0] },
{ key: "2015", values: [10, 5, 4, 3, 2, 1, 0] },
{ key: "2015", values: [10, 5, 4, 3, 2, 1, 0] },
{ key: "2015", values: [100, 5, 4, 3, 2, 1, 0] },
{ key: "2015", values: [10, 5, 4, 3, 2, 1, 0] },
]
const maxValue = (data) => {
// Setting an initial value to the lowest possible value in Javascript
let max = Number.MIN_VALUE;
// Iterate over each object in your array of data
data.forEach(({values}) => {
// Destructure the values from each object and then iterate over those
values.forEach(value => {
// Set the max to the higher over the current max or current value
max = Math.max(max, value);
})
})
// Return the max
return max;
}
console.log(maxValue(myData))
What we are doing here is iterating over each object in the initial array. Then iterating over the values keeping track of a current max.
Your data structure appears to be incorrect. You cannot have { '2015': values: [...] }. This would be the equivalent of { KEY: VALUE: VALUE}. The browser appears to be inferring meaning from your code and creating an object out of it anyway, but it's not right.
You can do an object of objects and have named inner objects, like this:
data = {
2015: {
values: [
{ key: "0", value: { count: 45 } },
{ key: "1", value: { count: 3 } },
],
},
2016: {
values: [
{ key: "0", value: { count: 67 } },
{ key: "1", value: { count: 0 } },
],
},
2017: {
values: [
{ key: "0", value: { count: 12 } },
{ key: "1", value: { count: 8 } },
],
},
};
Or you can create an array of objects, like this:
data = [
{
year: 2015,
values: [
{ key: "0", value: { count: 45 } },
{ key: "1", value: { count: 3 } },
],
},
{
year: 2016,
values: [
{ key: "0", value: { count: 67 } },
{ key: "1", value: { count: 0 } },
],
},
{
year: 2017,
values: [
{ key: "0", value: { count: 12 } },
{ key: "1", value: { count: 8 } },
],
},
];
How you get the highest count property depends on which data structure you use.
Using the array of objects, I would approach the problem like this:
// create a temp storage array to store "count" property of each
const countArray = [];
// iterate through the outer objects
for (const outerObject of data) {
// iterate through the objects that are in the "values" array
for (const innerObject of outerObject.values) {
// push the "count" value to the array
countArray.push(innerObject.value.count)
}
}
// sort the array in place, with highest values first
countArray.sort((a, b) => b - a);
// display the result
console.log(countArray[0])
You could do something similar for the object-of-objects data structure, but you'd need different syntax for that.

Javascript sort array of objects based on another array

I have an array of objects I need to sort based on another array objects. This is the given array that needs to be sorted:
const arr1 = [
{
id: 21,
name: 'Joey',
vehicle: 'car'
},
{
id: 6,
name: 'Kevin'
vehicle: 'car'
},
{
id: 10,
name: 'Luis'
vehicle: 'van'
}
]
And this is the array that is in the proper order:
const arr2 = [
{
id: 6,
name: 'Kevin'
},
{
id: 21,
name: 'Joey'
},
{
id: 10,
name: 'Luis'
}
]
There is no specific order to arr2 its just the data that comes back from my db. I basically just need to put the ids in arr1 in the same order as thet are in arr2.
Ive tried using findIndex and sort but I am very confused
that ?
const arr1 =
[ { id: 21, name: 'Joey', vehicle: 'car' }
, { id: 6, name: 'Kevin', vehicle: 'car' }
, { id: 10, name: 'Luis', vehicle: 'van' }
]
const arr2 =
[ { id: 6, name: 'Kevin' }
, { id: 21, name: 'Joey' }
, { id: 10, name: 'Luis' }
]
// Arr1 ordered..
const arr1_ord = arr2.map(a2=> arr1.find(x=>x.id===a2.id))
console.log( arr1_ord )
.as-console-wrapper {max-height: 100%!important;top:0}
Also, if there are only 2 items in arr2 I still want those elements that are missing to be at the end of the sorted arr1. Would this solve that?
I add add another case : arr2 element doesn't have a arr1 same id
const arr1 =
[ { id: 21, name: 'Joey', vehicle: 'car' }
, { id: 6, name: 'Kevin', vehicle: 'car' }
, { id: 12, name: 'George', vehicle: 'carriage' } // not in arr2
, { id: 10, name: 'Luis', vehicle: 'van' }
]
const arr2 =
[ { id: 6, name: 'Kevin' }
, { id: 21, name: 'Joey' }
, { id: 88, name: 'none' } // not in arr1
, { id: 10, name: 'Luis' }
]
// Arr1 ordered..
const arr1_ord = arr2.reduce((res, {id},i,{[i+1]:next})=>
{
let a1 = arr1.find(x=>x.id===id)
if (a1) res.push(a1) // if exist in arr1
if (next) return res
else return [...res, arr1.filter(r=>!res.some(z=>z.id===r.id))] // add the missing elements
},[])
console.log( arr1_ord )
.as-console-wrapper {max-height: 100%!important;top:0}
Array.prototype.sort can take in a custom comparison function to sort however you'd like it to.
The function takes in two arguments (firstValue, secondValue)
If that function returns a positive value, then secondValue goes before the firstValue, if it's 0 or negative, then firstValue is sorted before secondValue. First/second value are from the array you are sorting. In your case, you are sorting based on a different array, but that is fine since you can do that in your function.
You can do:
arr1.sort((firstValue, secondValue) => {
return findIdInArr2(firstValue.id) - findIdInArr2(secondValue.id);
});
Where you would have to define findIdInArr2 to find the index in arr2, and you can use Array.prototype.findIndex to solve that problem. Where findIndex similarly takes in a function to find the index of something in an array.
function findIdInArr2(id) {
const foundIndex = arr2.findIndex(function(obj) {
return obj.id === id;
});
// If not found, this will be -1. But that would sort all
// unfound objects at the beginning of the array.
// To place these objects at the end of the array, it needs to
// return a number higher than the rest. So return infinity.
return (foundIndex === -1) ? Infinity : foundIndex;
}
note: findIndex is not available in IE, so you'd need to add a polyfill if you are planning on supporting IE.

Mege multiple array object into single array object based on key

I have an array of objects of the structure coming from server response of iterated array object like as sample
var arrObj1 = [
{"id":"1","value":21, "value1":13},
{"id":"2","value":21, "value1":13 },
......n
];
var arrObj2 = [
{"id":"1","value3":21, "value14":13},
{"id":"2","value3":21, "value4":13 },
......n
];
var arrObj3 = [
{"id":"1","value5":21, "value6":13},
{"id":"2","value5":21, "value6":13 },
......n
];
But now I want to append the array values inot single new array according to key following structure of as iterated values of above array Expected Output:
var finalObj = [
{
"id" : 1
"value" : 21,
"value1" : 13,
"value3" : 21,
"value4" : 13,
"value5" : 21,
"value6" : 13,
},
{
"id" : 2
"value" : 21,
"value1" : 13,
"value3" : 21,
"value4" : 13,
"value5" : 21,
"value6" : 13,
},
.....n
];
You can use reduce for concated arrays
const arrObj1 = [
{ id: '1', value: 21, value1: 13 },
{ id: '2', value: 21, value1: 13 },
];
const arrObj2 = [
{ id: '1', value3: 21, value14: 13 },
{ id: '2', value3: 21, value4: 13 },
];
const arrObj3 = [
{ id: '1', value5: 21, value6: 13 },
{ id: '2', value5: 21, value6: 13 },
];
const result = [...arrObj1, ...arrObj2, ...arrObj3].reduce(
(acc, { id, ...rest }) => ({ ...acc, [id]: acc[id] ? { ...acc[id], ...rest } : { ...rest } }),
{},
);
console.log(Object.entries(result).map(([id, data]) => ({ id, ...data })));
Push you arrays to a new array (you have to have your sub arrays in other list to loop through them) and then use flat, after that group your object according to the id property
var arrObj1 = [{
"id": "1",
"value": 21,
"value1": 13
},
{
"id": "2",
"value": 21,
"value1": 13
},
];
var arrObj2 = [{
"id": "1",
"value3": 21,
"value14": 13
},
{
"id": "2",
"value3": 21,
"value4": 13
},
];
var arrObj3 = [{
"id": "1",
"value5": 21,
"value6": 13
},
{
"id": "2",
"value5": 21,
"value6": 13
},
];
const input = [];
input.push(arrObj2, arrObj3);
const preResult = input.flat();
result = preResult.reduce((acc, x) => {
const index = acc.findIndex(y => y.id === x.id)
if (index >= 0) {
acc[index] = {
...acc[index],
...x
}
} else {
acc.push(x)
}
return acc;
}, arrObj1)
console.log(result)
You can iterate over array-length and push here for every entry 1 entry to the result. For getting this entry take a new object with the id and iterate over all (3 or perhaps more) arrays. For every array take the i-th entry and push for every key an entry with key:value (except for the key id itself).
Remark: You can use as much arrays you want and every object could contain as much value-prperties as you need. The only restriction is that every array has the same count of objects.
var arrObj1 = [
{"id":"1","value":21, "value1":13},
{"id":"2","value":21, "value1":13 }
];
var arrObj2 = [
{"id":"1","value3":21, "value4":13},
{"id":"2","value3":21, "value4":13 }
];
var arrObj3 = [
{"id":"1","value5":21, "value6":13},
{"id":"2","value5":21, "value6":13 }
];
let result =[];
let arrayAll = [arrObj1, arrObj2, arrObj3];
for (let i=0; i<arrayAll[0].length; i++) {
let obj = arrayAll[0][i];
let res = { id: obj.id};
for (let j=0; j<arrayAll.length; j++) {
let obj = arrayAll[j][i];
Object.keys(obj).forEach(key => {
if (key!='id') res[key] = obj[key];
})
}
result.push(res);
}
console.log(result);
Since you are using id to merge multiple objects, Map is one of the good option to merge.
let arrObj1 = [
{"id":"1","value":21, "value1":13},
{"id":"2","value":21, "value1":13 },
];
let arrObj2 = [
{"id":"1","value3":21, "value14":13},
{"id":"2","value3":21, "value4":13 },
];
let arrObj3 = [
{"id":"1","value5":21, "value6":13},
{"id":"2","value5":21, "value6":13 },
];
let mergedArray = [...arrObj1,...arrObj2,...arrObj3].reduce((acc,curr) =>{
if(acc.has(curr.id)){
acc.set(curr.id, {...acc.get(curr.id),...curr});
}else{
acc.set(curr.id,curr);
}
return acc;
},new Map())
console.log(Array.from(mergedArray,x=>x[1]));

filter array of object using an array [duplicate]

This question already has an answer here:
Filter array of object from another array
(1 answer)
Closed 3 years ago.
I want to filter an array of objects using an array but I want the results on the basis of array index and the result should be repeated when the array index value is repeated.
const data = [{
id='1',
name:'x'
},
{
id='4',
name:'a'
},
{
id='2',
name:'y'
},
{
id='3',
name:'z'
}
]
cons idArray = [1,4,3,2,4,3,2]
I have tried following code and get the result only once
const filteredData = data.filter(arrayofObj => idArray.includes(arrayofObj.id))
console.log(filteredData)
expected output is
expected output is =
[{id = '1,name:'x'},{id='4',name:'a'},{
id='3',
name:'z'
},
{
id='2',
name:'y'
},{
id='4',
name:'a'
},
{
id='3',
name:'z'
},{
id='2',
name:'y'
}]
First convert data array into Object with id's as keys.
Second, use map method over idArray and gather objects from above object.
const data = [
{
id: "1",
name: "x"
},
{
id: "4",
name: "a"
},
{
id: "2",
name: "y"
},
{
id: "3",
name: "z"
}
];
const dataObj = data.reduce((acc, curr) => {
acc[curr.id] = { ...curr };
return acc;
}, {});
const idArray = [1, 4, 3, 2, 4, 3, 2];
const results = idArray.map(id => ({ ...dataObj[id] }));
console.log(results);
You could map with a Map.
const
data = [{ id: '1', name: 'x' }, { id: '4', name: 'a' }, { id: '2', name: 'y' }, { id: '3', name: 'z' }],
idArray = [1, 4, 3, 2, 4, 3, 2],
result = idArray.map(Map.prototype.get, new Map(data.map(o => [+o.id, o])));
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Parse data into JSON

I have one specific problem that I'm having difficulty Googling the answer for.
This is the code:
records.forEach(function(record){
var personID = record.id;
var personsInterest = record.interest;
console.log(personID);
console.log(personsInterest);
console.log();
}
It outputs the following:
138
death note
146
poop
138
poop
146
rick and morty
138
rick and morty
138
lil peep
145
420
I would really like the code to store the data like this
[
{
id: "138",
interests:["death note","poop","rick and morty","lil peep"]
},
{
id: "146",
interests:["poop","rick and morty"]
},
{
id: "145",
interests:["420"]
}
]
where they are ordered by the length of the interests array
This should work. Annotated in comments.
const records = [{
id: 138,
interest: 'death note'
},
{
id: 146,
interest: 'poop'
},
{
id: 138,
interest: 'poop'
},
{
id: 146,
interest: 'rick and morty'
},
{
id: 138,
interest: 'rick and morty'
},
{
id: 138,
interest: 'lil peep'
}
];
const sorted = records.reduce((all, record) => {
const person = all.find(p => p.id === record.id);
//If already exists person now contains existing person
if (person) {
person.interests.push(record.interest);
//add new interest
} else all.push({
id: record.id,
interests: [record.interest]
//creates new person object
});
return all;
}, []).sort((a, b) => b.interests.length - a.interests.length);
//sorts based on length of interest array
console.log(sorted);
To achieve expected result, use below option
Loop main arr using forEach
Created result arr
Add new object to result arr
Else push to interest array
let records = [
{
id: 138,
interests: "death note"
},
{
id: 146,
interests: "poop"
},
{
id: 138,
interests: "poop"
},
{
id: 146,
interests: "rick and morty"
},
{
id: 138,
interests: "rick and morty"
},
{
id: 138,
interests: "lil peep"
},
{
id: 145,
interests: "420"
}
];
let result = [];
records.forEach(record => {
if (result.filter(item => item.id == record.id).length == 0) {
// check whether id exists in result array, if not push object to result array
result.push({ id: record.id, interests: [record.interests] });
} else {
//if id already exists in result array, push interest to interest array of that id
result.forEach(v => {
if (v.id == record.id) {
v.interests.push(record.interests);
}
});
}
});
console.log(result);
codepen - https://codepen.io/nagasai/pen/Pxmwjp?editors=1010
Use sort method with a suitable compareFunction to sort your array. arr.sort(compareFunction(a,b))
Sort method takes a function and sorts the elements of the array according to the return value of the function supplied. Let's call the function compareFunction(a, b).
If the return value of compareFunction(a, b) is less than 0: a comes first.
If the return value of compareFunction(a, b) is more than 0: b comes first.
If the return value of compareFunction(a, b) is 0: does nothing.
You want the element which has the higher interest.length comes first. So we can return b.interest.length - a.interest.length.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort
var records = [{
id: 10,
interest: ["poop", "rick and morty"]
},
{
id: 11,
interest: ["eminem", "snoop dog"]
},
{
id: 12,
interest: ["death note", "poop", "rick and morty", "lil peep"]
},
{
id: 13,
interest: ["god of war"]
},
];
records = records.sort((a, b) => b.interest.length - a.interest.length);
console.log(records);

Categories