In JavaScript, I'm trying to create arrays based on the values of another array and I'm having difficultly.
I've got an array of dates in string format (dates) e.g.
["30/09/2015", "31/10/2015", "30/11/2015", "31/12/2015"]
I've got an Object to represent multiple bank accounts (balancesSortByAccId) e.g.
Cash - (Array size: 3)
id: 1, date: "30/09/2015", balance: 30
id: 2, date: "31/10/2015", balance: 50
id: 3, date: "30/11/2015", balance: 100
Natwest - (Array size: 2)
id: 4, date: "30/11/2015", balance: 400
id: 5, date: "31/12/2015", balance: 200
Whilst looping through all the accounts in balancesSortByAccId, I want to be able to create an array for the balance at each date in the dates array i.e.
[30, 50, 100, null]
[null, null, 400, 200]
How could I achieve this?
UPDATE: jsfiddle code - https://jsfiddle.net/gx8bLehb/
The easiest way would be to transform your cash and natwest arrays into a hash sorted by date, something like balancesByDate:
var balancesByDate = _.groupBy(cash, function(entry) {return entry.date});
Then use an array map() function, e.g. from lodash to iterate the dates array and for each date look up the account line in the balancesByDate hash. From that line, return the balance property in the map function.
dates.forEach(function(date){
if (balancesByDate[date]) {
results.push(_.map(balancesByDate[date], function(line){
return line.balance;
}));
} else {
results.push(null);
}
});
However, you need to be aware that your dataset most likely could contain duplicate balances for a day, you should plan for that (my code returns an array for each day).
https://jsfiddle.net/hdpuuc5d/1/
A solution in plain javascript with a helper object for the dates:
var dates = ["30/09/2015", "31/10/2015", "30/11/2015", "31/12/2015"],
datesObj = dates.reduce(function (r, a, i) { r[a] = i; return r; }, {}),
balances = {
Cash: [
{ id: 1, date: "30/09/2015", balance: 30 },
{ id: 2, date: "31/10/2015", balance: 50 },
{ id: 3, date: "30/11/2015", balance: 100 }
],
Natwest: [
{ id: 4, date: "30/11/2015", balance: 400 },
{ id: 5, date: "31/12/2015", balance: 200 }
]
},
result = {};
Object.keys(balances).forEach(function (k) {
result[k] = Array.apply(null, { length: dates.length }).map(function () { return null; });
balances[k].forEach(function (a) {
result[k][datesObj[a.date]] = a.balance;
});
});
document.write('<pre>' + JSON.stringify(result, 0, 4) + '</pre>');
Related
I have the following input of an array of objects:
[
{
timestamp: 1602754921328,
product: "productA"
},
{
timestamp: 1602754921942,
product: "productB"
},
{
timestamp: 1602754924160,
product: "productA"
},
{
timestamp: 1602757547704,
product: "productB"
},
{
timestamp: 1602757563480,
product: "productC"
},
{
timestamp: 1602757567032,
product: "productB"
}
]
where the timestamp is a unix timestamp and the product any string value.
The input array consists of values ranging from start of day to end of day, so 24 hours.
The goal is to split these values into segments of 4 hours, so 6 different segments and have these segments filled with the number of times the value occurred in the array within the 4 hour period.
The expected output would be:
[
{
name: "productA",
data: [0, 0, 2, 0, 0, 0]
},
{
name: "productB",
data: [0, 0, 1, 2, 0, 0]
},
{
name: "productC",
data: [0, 0, 0, 1, 0, 0]
},
]
The output consists of each value that was found in the input array, with an array (let's call it data) consisting of 6 values, where each of these values are the amount of times the value was found in the array for the specific 4 hour period.
I have managed to split the input data into 6 arrays that correspond to the individual 4 hour periods, but I am not sure if this is correct approach for the first step and I am having trouble in getting from this step to the needed output.
Grateful for any directions, I am using javascript to write the function.
You could group with the product and get an index fro counting a certain slot of the timestamp.
const
data = [{ timestamp: 1602754921328, product: "productA" }, { timestamp: 1602754921942, product: "productB" }, { timestamp: 1602754924160, product: "productA" }, { timestamp: 1602757547704, product: "productB" }, { timestamp: 1602757563480, product: "productC" }, { timestamp: 1602757567032, product: "productB" }],
getIndex = t => Math.floor(Math.floor(t / 1000 / 60 / 60) % 24 / 4),
result = Object.values(data.reduce((r, { timestamp, product: name }) => {
if (!r[name]) r[name] = { name, data: Array(6).fill(0) };
r[name].data[getIndex(timestamp)]++;
return r;
}, {}));
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
I have an array as below.
const list = [
{
date: "2020-01-01",
number: 3,
count: 2
},
{
date: "2020-01-01",
number: 3,
count: 2
},
{
date: "2020-01-01",
number: 3,
count: 2
},
{
date: "2020-01-02",
number: 4,
count: 1
},
{
date: "2020-01-02",
number: 4,
count: 1
}
]
And I want to sum number and count depends on same date. After that it should be merged in same date. Therefore I want to get the result as below.
const list = [{
totalNumber: 9,
totalCount: 6,
detail:[{
date: "2020-01-01",
number: 3,
count: 2
},
{
date: "2020-01-01",
number: 3,
count: 2
},
{
date: "2020-01-01",
number: 3,
count: 2
}]
},
{
totalNumber: 8,
totalCount: 2,
detail:[
{
date: "2020-01-02",
number: 4,
count: 1
},
{
date: "2020-01-02",
number: 4,
count: 1
}]
}
]
I know stackoverflow is not code writing site. But I made this from some data. But this is my last stage for completing my object. And I don't know how I can group like that. I'' appreciate if you help me to resolve this problem. Thank you so much for reading it.
To me, optimal approach is building Map (having necessary property as a key) with Array.prototype.reduce(), then extracting array of values (aggregated records) with Map.prototype.values():
const src = [{date:"2020-01-01",number:3,count:2},{date:"2020-01-01",number:3,count:2},{date:"2020-01-01",number:3,count:2},{date:"2020-01-02",number:4,count:1},{date:"2020-01-02",number:4,count:1}],
groupped = [...src
.reduce((acc, {date, number, count}) => {
const group = acc.get(date)
if(group){
group.totalNumber += number
group.totalCount += count
group.detail.push({date, number, count})
} else {
acc.set(
date,
{
date,
totalNumber: number,
totalCount: count,
detail: [{
date,
number,
count
}]
}
)
}
return acc
}, new Map)
.values()
]
console.log(groupped)
.as-console-wrapper{min-height:100%;}
Below is array.
What I have to do is sort array according to latest date.
So basically if you look the code after sorting id:12 should come before id:23
I have tried
myArray.sort(function(a, b) {
return a.date- b.date;
});
but it is not working
0:
{ id: 23
name: "joe"
price: 2300
date: "2018-06-01T09:48:18.000Z"},
1:
{ id: 12
name: "ali"
price: 300
date: "2018-09-01T09:48:1i.000Z"},
the following example explains how to sort the array by dates
var array=[{'date':'2018-06-05T09:48:18.000Z'},{'date':'2018-06-01T09:48:18.000Z'},{'date':'2018-04-01T09:48:18.000Z'}];
array.sort(function(a,b){
//convert your string into dates
return new Date(a.date) - new Date(b.date);
});
console.log(array)
By using an ISO 8601 compliant date, you could take the strings directly for sorting with String#localeCompare.
var array = [{ id: 23, name: "joe", price: 2300, date: "2018-06-01T09:48:18.000Z" }, { id: 12, name: "ali", price: 300, date: "2018-09-01T09:48:1i.000Z" }];
array.sort(function(a, b) {
return b.date.localeCompare(a.date); // desc
});
console.log(array);
is possible with lodash library group elements by 2 properties?
I have array of objects like this:
[{
id: 1,
amount: 2000,
date: "2018-01-31T00:00:00.000Z"
},{
id: 2,
amount: 3000,
date: "2017-07-31T00:00:00.000Z"
},{
id: 3,
amount: 6000,
date: "2018-01-31T00:00:00.000Z"
},{
id: 4,
amount: 7000,
date: "2017-01-31T00:00:00.000Z"
},{
id: 5,
amount: 5000,
date: "2017-03-31T00:00:00.000Z"
},{
id: 6,
amount: 3000,
date: "2018-02-22T00:00:00.000Z"
},{
id: 7,
amount: 4500,
date: "2017-01-31T00:00:00.000Z"
}]
My goal is group objects in array by:
year
month
Purpose of that grouping is that I need in result order these objects' sum of amount by newest. So for that reason I need distinguish January 2017 from January 2018. It should be 2 different groups.
I am not sure if my approach is correct so I write here my required output:
[
3000, // sum of 2018-2
8000, // sum of 2018-1
3000 // sum of 2017-7
5000 // sum of 2017-3
11500 // sum of 2017-1
]
I tried following command but it doesn't work and give me error:
let xxx = _(data)
.groupBy(function(i) {
new Date(i.date).getFullYear()
})
.groupBy(function(i) {
new Date(i.date).getMonth()
})
.map(x => x.amount)
.sum()
.orderBy('date').value();
Can you help me to fix it ? Thanks.
You can just concat your year and month with groupBy and use it.
var grouped = _.groupBy(data, function(i) {
return new Date(i.date).getFullYear()+'-'+new Date(i.date).getMonth()
})
var resultUnsorted = _.map(t, (val, key) => ({key: key, val: val.reduce((p, c) => c.amount + p, 0) }));
then sort using _.orderBy
const output = _.orderBy(resultUnsorted, 'key');
you can write your custom sort function using the behaviour you want.
let arr = [{
name: 'Apple',
trades: [{
date: '2017.01.01',
volume: 100
}, {
date: '1995.02.01',
volume: 150
}, {
date: '2008.01.01',
volume: 250
}]
}]
Hello, I googled many documents for sorting nested object in JavaScript, but I couldn't find the way of my case and I struggled so many hours so I want to ask to how can I sort above array of objects.
What I expected result is sort array of object by trades.date like this
sortedArray = [{
name: 'Apple',
trades: [{
date: '2017.01.01',
volume: 100
}, {
date: '2008.01.01',
volume: 250
}, {
date: '1995.02.01',
volume: 150
}]
}]
How can I do this?
arr[0].trades.sort(function(a, b) {
return (new Date(b.date) - new Date(a.date));
});
You can use the array's sort method for achieving this. If you want to sort in the reverse order then just swap a and b in the return code.
Read about array.sort() and datetime in Javascript.
let arr = [{
name: 'Apple',
trades: [{
date: '2017.01.01',
volume: 100
}, {
date: '1995.02.01',
volume: 150
}, {
date: '2008.01.01',
volume: 250
}]
}]
console.log(arr[0].trades.sort((tradeA, tradeB)=>{
return (new Date(tradeA.date) - new Date(tradeB.date)) * (-1)
// or return (new Date(tradeB.date) - new Date(tradeA.date))
}))
First in your array, date needs to be a string. You can than use arrays.sort with a function which returns the result
let arr = [
{
name : 'Apple',
trades : [
{date : "2017.01.01",
volume : 100
},
{date : "1995.02.01",
volume : 150
},
{date : "2008.01.01",
volume : 250
}
]
}
]
function compare(a,b) {
var dateA = new Date(a.date);
var dateB = new Date(b.date);
if (dateA > dateB)
return -1;
if (dateA < dateB)
return 1;
return 0;
}
arr[0].trades.sort(compare);
console.log(arr);
Ensure your date format, dot is not an iso delimiter.
let toArr = (aDate) => aDate.split('.')
let toDate = ([year, month, day]) => new Date(year, month - 1, day)
let compareTrades = (a, b) => toDate(toArr(a.date)) - toDate(toArr(b.date))
let arr = [{
name: 'Apple',
trades: [{
date: '2017.01.01',
volume: 100
}, {
date: '1995.02.01',
volume: 150
}, {
date: '2008.01.01',
volume: 250
}]
}]
arr[0].trades.sort(compareTrades)
console.log(arr[0])