Related
I have an array with over 50 entries in the form of objects, which I would like to save depending on the Item ID so that I can then apply certain calculations to them. For example, I would like to add up the time of all entries with the Item Id "Las5241Wz".
Since the array can change dynamically, I can't analyze it manually. How can I separate the data beforehand according to their Item ID and push them into new arrays? The real Array contains up to 16 objects with the same ID.
var data= []
data = [
//...objects
{
itemId: "Las5241Wz",
time: 10
},
{
itemId:"Bos1239Zf",
time: 11
},
{
itemId:"Las5241Wz",
time: 15
},
{
itemId:"Bos1239Zf",
time: 21
}
//...more objets
]
The solution for this should look like this:
var Item1 = [
{
itemId: "Las5241Wz",
time: 10
},
{
itemId:"Las5241Wz",
time: 15
},
]
var Item2 = [
{
itemId:"Bos1239Zf",
time: 11
},
{
itemId:"Bos1239Zf",
time: 21
}
]
Here is another solution that builds an object with the properties "item1", "item2" and so on from the given object:
const data = [
//...objects
{
itemId: "Las5241Wz",
time: 10
},
{
itemId:"Bos1239Zf",
time: 11
},
{
itemId:"Las5241Wz",
time: 15
},
{
itemId:"Bos1239Zf",
time: 21
}
//...more objets
]
console.log(
Object.values(
data.reduce((o,e)=>((o[e.itemId]=o[e.itemId]||[]).push(e),o),{}))
.reduce((o,c,i)=>(o["item"+(i+1)]=c,o),{})
);
This is a "one-liner" and for that reason not that easy to read. So, probably not the version you would put into your production code.
Unless you have a performance reason to keep the lists separately, the answer is that you can just store the list of ids as a Set and use array.filter when you want to get the list that is just for that id
Set s = new Set();
for (let i = 0; i < data.length; i++) {
s.add(data[i].itemId);
}
var createFilterFunc(id) {
return function(elem) {
return elem.itemId == id;
}
}
var items = data.filter (createFilterFunc("Las5241Wz"));
Overview
I need to make a chart in my react project.
Using data from a json (Object Array).
Example json:
[
{recruiter_id: 1, datetime_created: "1/01/2021", name: "Aaron"},
{recruiter_id: 2, datetime_created: "9/01/2021", name: "Bob"},
{recruiter_id: 1, datetime_created: "9/01/2021", name: "Aaron"},
{recruiter_id: 3, datetime_created: "20/01/2021", name: "Jane"}
]
Result object array structure required:
[
{name: name,
recruiter_id: recruiter_id,
week_qty: [0,2,1,0,2,0,0,0,0,0,0,0,0,1,0,0,0,...] },
...]
// week_qty will be an array of 52 to represent each week of the year. It will be a 0 if there was no dates for that week.
Goal
This is what the new object array should look like, if we used the example json.
[
{name: "Aaron", recruiter_id:1, week_qty: [1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,...]},
{name: "Bob", recruiter_id:2, week_qty: [0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,...]},
{name: "Jane", recruiter_id:3, week_qty: [0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,...]}
]
What I have
I dont have any working code yet. I am currently working on object[0] to attempt to put the dates into the 52 array. And then after that I will then turn it into a loop to work on each object. Once I have it semi working, I will post it for example.
--- Edit ---
var array = result
var flags = [], output = [], l = array.length, i;
for (i = 0; i < l; i++) {
if (flags[array[i].recruiter_id]) continue;
flags[array[i].recruiter_id] = true;
var temp = {}
temp.Recruiter_id = array[i].recruiter_id
temp.Name = array[i].name
temp.QTY = []
output.push(temp);
}
console.log("output : ", output)
This produces the new object array structure with the id and name filled out.
[
{name: name,
recruiter_id: recruiter_id,
week_qty: [] },
...]
It only has 1 object for each id
Now I need to work on getting the week numbers for the dates and put them into each of those objects.
Question
Any code suggestions on how to get this result?
Side Note
If your curious to know how I then plan on using the new object array to use with my chart.
I will let the user select the week. Lets say week 1.
I will then map through the object array and get the week_qty for index 1 and the name value of the object.
I will store that week_qty and the name in a new new object array.
That new new object array will then look like this
[{name: "Aaron",QTY: 2},{name: "Bob",QTY: 1,]
That will then be passed as the x and y value to the chart.
You can use reduce and increase the week counter after parsing each date and getting the week (using moment.js for that part here)
But you can see Get week of year in JavaScript like in PHP for more details on how to calculate it yourself
const data = [
{recruiter_id: 1, datetime_created: "1/01/2021", name: "Aaron"},
{recruiter_id: 2, datetime_created: "9/01/2021", name: "Bob"},
{recruiter_id: 1, datetime_created: "9/01/2021", name: "Aaron"},
{recruiter_id: 3, datetime_created: "20/01/2021", name: "Jane"}
];
const weekly = data.reduce((acc, item, index, array) => {
const {
recruiter_id,
datetime_created,
name
} = item;
let existing = acc.find(({
recruiter_id: id
}) => id === recruiter_id);
if (!existing) {
existing = {recruiter_id, name, week_qty:Array(52).fill(0)};
acc.push(existing);
}
const week = moment(datetime_created,'D/M/YYYY').week()-1;
existing.week_qty[week]++;
return acc;
}, []);
console.log(JSON.stringify(weekly))
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.29.1/moment.min.js" integrity="sha512-qTXRIMyZIFb8iQcfjXWCO8+M5Tbc38Qi5WzdPOYZHIlZpzBHG3L3by84BBBOiRGiEb7KKtAOAs5qYdUiZiQNNQ==" crossorigin="anonymous"></script>
It might be a very basic question for people here but I have to ask away.
So I was going through reducce recently and I came through this example where I could find the maximum of some value in an array of object. Please, have a look at this code.
var pilots = [
{
id: 10,
name: "Poe Dameron",
years: 14
}, {
id: 2,
name: "Temmin 'Snap' Wexley",
years: 30
}, {
id: 41,
name: "Tallissan Lintra",
years: 16
}, {
id: 99,
name: "Ello Asty",
years: 22
}
];
If I write soemthing like this to find the maximum years,
var oldest_of_them_all = pilots.reduce(function (old, current) {
var old = (old.years > current.years) ? old.years : current.years;
return old
})
I get 22 as my value, and if I dont involve the property years, i.e-
var oldest_of_them_all = pilots.reduce(function (old, current) {
var old = (old.years > current.years) ? old : current;
return old
})
I get the object Object {id: 2, name: "Temmin 'Snap' Wexley", years: 30} as my value. Can someone explain why the first example is wrong and what is happening in there? Also, if I Just want to fetch the years value, how can I do that? Thanks in advance.
In the first example, as you are not returning the object there is no object property (years) of the accumulator (old) after the first iteration. Hence there is no year property to compare with.
var pilots = [
{
id: 10,
name: "Poe Dameron",
years: 14
}, {
id: 2,
name: "Temmin 'Snap' Wexley",
years: 30
}, {
id: 41,
name: "Tallissan Lintra",
years: 16
}, {
id: 99,
name: "Ello Asty",
years: 22
}
];
var oldest_of_them_all = pilots.reduce(function (old, current) {
console.log(old);// the value is not the object having the property years after the first iteration
var old = (old.years > current.years) ? old.years : current.years;
return old;
})
console.log(oldest_of_them_all);
I receive an array of posts through an API and want to merge the ones with the same "month" and "year" (day is not important), into one object. I looked up for answers but there are just too many foo-bar examples that confuses more than helping. I want to know the cleanest, most elegant way of handling such problems, without getting into call-back hell and nested blocks...
Here is the API response:
0:
{
date: {day: 27, month: 1, year: 2020}
id: 3
}
1:
{
date: {day: 28, month: 1, year: 2020}
id: 4
}
2:
{
date: {day: 31, month: 1, year: 2020}
id: 5
}
3:
{
date: {day: 1, month: 2, year: 2020}
id: 6
}
4:
{
date: {day: 2, month: 2, year: 2020}
id: 7
}
The expected outcome:
0:
result: {month: 1, year: 2020, id:[3,4,5]}
1:
result: {month: 2, year: 2020, id:[6,7]}
One approach would be to use the Array#reduce() method to transform the input array into a dictionary, where each value contains the accumulation of id's for that month and year. Once this dictionary has been built, you could then extract the values of that dictionary to an array via Object#values() to obtain the required output:
let input=[{date:{day:27,month:1,year:2020},id:3},{date:{day:28,month:1,year:2020},id:4},{date:{day:31,month:1,year:2020},id:5},{date:{day:1,month:2,year:2020},id:6},{date:{day:2,month:2,year:2020},id:7}];
/* Convert the dictionary that will be created by reduce to a value array */
var output = Object.values(input.reduce((dict, item) => {
const { date, id } = item;
/* The distinct key for this item based on month/year of date field */
const key = `${date.month}-${date.year}`;
/* Check if dictionary already has an object value for key. This short hand
will only insert a new object value for key, if one does not already exist
in the dictionary */
const value = dict[key] || { month : date.month, year : date.year, id : [] };
/* Add the item id to the dictionary entries id array */
value.id.push(id);
/* Update value object for key */
return { ...dict, [key] : value };
}, {}))
console.log(output);
The idea here is that the dictionary is built using Compound Keys, where the keys are derived from the month and year of the current array item.
When no value exists for the current key, a new value object is inserted to the dictionary for that key:
{ month : date.month, year : date.year, id : [] }
The id of the current array item is then added (accumulated) to the id sub array of the object for that key:
dict[key].id.push(id);
Hope that helps
Here is an alternate approach, if you are not a big fan of Array.reduce and Array.values and also, if you like to consider performance when running the response for a larger data set.
This approach avoids cloning object (or rather non-mutating object) with spread operator i.e {...<anyObject>} while iterating. which should be fine for minimal set of data but but definitely not when you deal with huge volume.
const response = [{
date: { day: 27, month: 1, year: 2020 },
id: 3
}, {
date: { day: 28, month: 1, year: 2020 },
id: 4
}, {
date: { day: 31, month: 1, year: 2020 },
id: 5
},{
date: { day: 1, month: 2, year: 2020 },
id: 6
},{
date: { day: 2, month: 2, year: 2020 },
id: 7
}];
function groupByMonthYear(response) {
// output
const groupedData = []
// Using map for lookup to avoid iterating again on the grouped data
const referenceMap = new Map();
// destructing month, year and id from the response
for (const { date: { month, year }, id } of response) {
const groupKey = `${month}${year}`
// check if the month and year reference is already seen using the groupKey MMYYYY
if (referenceMap.has(groupKey)) {
referenceMap.get(groupKey).id.push(id);
// early return
continue;
}
// simply add a new entry if it doesn't exist
const data = {
month,
year,
id: [id]
};
groupedData.push(data);
referenceMap.set(groupKey, data)
}
return groupedData;
}
// Invoke and Print the result
console.log(groupByMonthYear(response));
I am working on a small VueJS webapp. I would like to output data from my array to the view but it has to be the last item of an array and of that last item the second item which is a and in my example equel to 39. I don't know how I can recieve that one.
HTML
<p>The last number in the array (a) is {{userLastCount}} </p>
Javascript/Vue
data () {
return {
event: 'Custom event',
userLastCount: 0,
lineData: [
{ time: '2017-05-01 15:00', a: 0 },
{ time: '2017-05-01 16:00', a: 12 },
{ time: '2017-05-01 17:00', a: 23 },
{ time: '2017-05-01 18:00', a: 28 },
{ time: '2017-05-01 19:00', a: 39 },
]
}
},
components: {
DonutChart, BarChart, LineChart, AreaChart
},
created() {
this.userLastCount = //equal to 39
}
I would like to output the last value of 'a' of the lineData object and assign it to a data string which I can output to the view. So, now the last 'a' = 39. But if I add another row in my object It has to be that one that is assigning to this.userLastCount
The last item of an array is arr[arr.length - 1]. You can use a computed to have that value always set for you, rather than maintaining a data item yourself:
computed: {
userLastCount() {
return this.lineData[this.lineData.length - 1].a;
}
}
Ypu can do this uzing plain javascript
In your created() hook do as follows:
created(){
//get the position of last object in the array.
var lastPosition = this.lineData.length -1;
this.userLastCount = this.lineData[lastPosition].a;
}