Related
I have an object like the following:
data_sample = {
"object_1": {
"irrelevant_data1": 0,
"irrelevant_data2": 0,
"data_needed_to_sum_up": 100,
},
"object_a": {
"irrelevant_data1": 0,
"irrelevant_data2": 0,
"irrelevant_data3": 0,
"data_needed_to_sum_up": 200,
},
"object_d": {
"irrelevant_data1": 0,
"irrelevant_data2": 0,
"data_needed_to_sum_up": 300,
},
}
How can I use the reduce method to get the sum of all data_needed_to_sum_up inside data_sample to get the expected result of 600?
You could use Object.valuesto and then use reduce
data_sample = { "object_1": { "irrelevant_data1": 0, "irrelevant_data2": 0, "data_needed_to_sum_up": 100, }, "object_a": { "irrelevant_data1": 0, "irrelevant_data2": 0, "irrelevant_data3": 0, "data_needed_to_sum_up": 200, }, "object_d": { "irrelevant_data1": 0, "irrelevant_data2": 0, "data_needed_to_sum_up": 300, }, }
res = Object.values(data_sample)
.reduce((acc,curr) => acc = acc + curr["data_needed_to_sum_up"],0)
console.log(res)
.reduce works on arrays, what you have is just an object, but you could use .reduce in conjunction with Object.entries, like so:
data_sample = {
"object_1": {
"irrelevant_data1": 0,
"irrelevant_data2": 0,
"data_needed_to_sum_up": 100,
},
"object_a": {
"irrelevant_data1": 0,
"irrelevant_data2": 0,
"irrelevant_data3": 0,
"data_needed_to_sum_up": 200,
},
"object_d": {
"irrelevant_data1": 0,
"irrelevant_data2": 0,
"data_needed_to_sum_up": 300,
},
}
console.log(Object.entries(data_sample).reduce((carry, [_, current]) => carry + current.data_needed_to_sum_up, 0))
You can use Array#reduce on Object.values.
let sum = Object.values(data_sample)
.reduce((acc,cur)=>acc+cur.data_needed_to_sum_up,0);
Try this:
console.log(Object.values(data_sample).map((x) => x.data_needed_to_sum_up).reduce((x, y) => x + y));
use Object.valuesto first then use reduce
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 2 years ago.
Improve this question
I think I achieve my goal but I'm sure that it is not the best approach to do it.
I have a function and there is a issue that make it to add some extra [0], I got that is because the while test keep going. I don't need to do it with while+splice. I would like some suggestion to make it easier. My goal is from a provided array, create new arrays always starting from a element different from 0 and the length will be provided as k:
function splitNumber(arrayProvided, k) {
let newArray = [];
while (arrayProvided.length > 0) {
newArray.push(
arrayProvided.splice(
arrayProvided.findIndex(el => el),
k
)
);
}
return newArray;
}
console.log(
splitNumber([1, 0, 4, 6, 0, 7, 8, 4, 2, 0, 8, 3, 0, 0, 0, 0, 0, 0, 0, 6], 4)
);
The result for this code is:
[
[ 1, 0 ], [ 4, 6 ],
[ 7, 8 ], [ 4, 2 ],
[ 8, 3 ], [ 6 ],
[ 0 ], [ 0 ],
[ 0 ], [ 0 ],
[ 0 ], [ 0 ],
[ 0 ], [ 0 ],
[ 0 ]
]
It's correctly partially because the system is having a extra working after the job done adding extra [0]. The system cannot start with a 0 value in the first array position and no need extra [0] (It's happens because the logic is not totally right), and Yes the lenght of the new arrays is the k value.
Without zeroes, you could add another check and omit unwanted zeroes.
This approach does not mutate the given data.
function splitNumber(array, k) {
let result = [],
i = 0;
while (i < array.length) {
if (array[i] === 0) {
i++;
continue;
}
result.push(array.slice(i, i += k));
}
return result;
}
console.log(splitNumber([1, 0, 4, 6, 0, 7, 8, 4, 2, 0, 8, 3, 0, 0, 0, 0, 0, 0, 0, 6], 4));
I think its already a pretty smart solution to use findIndex to implicitly check for non-zero indeces. However, you need to handle when it returns -1 as is the case when no non-zero entries was found. So putting a check for that solves your issue.
function splitNumber(arrayProvided, k) {
let newArray = [];
while (arrayProvided.length > 0) {
let nonZeroStartIndex = arrayProvided.findIndex(el => el )
if( nonZeroStartIndex == -1 ){
break;
}
else{
newArray.push(
arrayProvided.splice( nonZeroStartIndex , k )
);
}
}
return newArray;
}
console.log(
splitNumber([1, 0, 4, 6, 0, 7, 8, 4, 2, 0, 8, 3, 0, 0, 0, 0, 0, 0, 0, 6], 4)
);
Then, the check can be moved up to the while loop to let it gracefully exit when no more non-zero entries can be found
function splitNumber(arrayProvided, k) {
let newArray = [];
let nonZeroStartIndex = arrayProvided.findIndex(el => el )
while (nonZeroStartIndex != -1) {
newArray.push( arrayProvided.splice( nonZeroStartIndex, k ) );
nonZeroStartIndex = arrayProvided.findIndex(el => el )
}
return newArray;
}
console.log(
splitNumber([1, 0, 4, 6, 0, 7, 8, 4, 2, 0, 8, 3, 0, 0, 0, 0, 0, 0, 0, 6], 4)
);
I am developing an application. I am getting a response from the AJAX request like this:
{
"country": "italy",
"timeline": {
"cases": {
"1/22/20": 0,
"1/23/20": 0,
"1/24/20": 0,
"1/25/20": 0,
"1/26/20": 0,
"1/27/20": 0,
"1/28/20": 0,
"1/29/20": 0,
"1/30/20": 0,
"1/31/20": 2,
"2/1/20": 2,
"2/2/20": 2,
"2/3/20": 2,
"2/4/20": 2,
"2/5/20": 2,
"2/6/20": 2,
"2/7/20": 3,
"2/8/20": 3,
"2/9/20": 3,
"2/10/20": 3,
"2/11/20": 3,
"2/12/20": 3,
"2/13/20": 3,
"2/14/20": 3,
"2/15/20": 3,
"2/16/20": 3,
"2/17/20": 3,
"2/18/20": 3,
"2/19/20": 3,
"2/20/20": 3,
"2/21/20": 20,
"2/22/20": 62,
"2/23/20": 155,
"2/24/20": 229,
"2/25/20": 322,
"2/26/20": 453,
"2/27/20": 655,
"2/28/20": 888,
"2/29/20": 1128,
"3/1/20": 1694,
"3/2/20": 2036,
"3/3/20": 2502,
"3/4/20": 3089,
"3/5/20": 3858,
"3/6/20": 4636,
"3/7/20": 5883,
"3/8/20": 7375,
"3/9/20": 9172,
"3/10/20": 10149,
"3/11/20": 12462,
"3/12/20": 12462,
"3/13/20": 17660,
"3/14/20": 21157,
"3/15/20": 24747,
"3/16/20": 27980,
"3/17/20": 31506,
"3/18/20": 35713,
"3/19/20": 41035,
"3/20/20": 47021,
"3/21/20": 53578,
"3/22/20": 59138,
"3/23/20": 63927,
"3/24/20": 69176,
"3/25/20": 74386,
"3/26/20": 80589,
"3/27/20": 86498
},
"deaths": {
"1/22/20": 0,
"1/23/20": 0,
"1/24/20": 0,
"1/25/20": 0,
"1/26/20": 0,
"1/27/20": 0,
"1/28/20": 0,
"1/29/20": 0,
"1/30/20": 0,
"1/31/20": 0,
"2/1/20": 0,
"2/2/20": 0,
"2/3/20": 0,
"2/4/20": 0,
"2/5/20": 0,
"2/6/20": 0,
"2/7/20": 0,
"2/8/20": 0,
"2/9/20": 0,
"2/10/20": 0,
"2/11/20": 0,
"2/12/20": 0,
"2/13/20": 0,
"2/14/20": 0,
"2/15/20": 0,
"2/16/20": 0,
"2/17/20": 0,
"2/18/20": 0,
"2/19/20": 0,
"2/20/20": 0,
"2/21/20": 1,
"2/22/20": 2,
"2/23/20": 3,
"2/24/20": 7,
"2/25/20": 10,
"2/26/20": 12,
"2/27/20": 17,
"2/28/20": 21,
"2/29/20": 29,
"3/1/20": 34,
"3/2/20": 52,
"3/3/20": 79,
"3/4/20": 107,
"3/5/20": 148,
"3/6/20": 197,
"3/7/20": 233,
"3/8/20": 366,
"3/9/20": 463,
"3/10/20": 631,
"3/11/20": 827,
"3/12/20": 827,
"3/13/20": 1266,
"3/14/20": 1441,
"3/15/20": 1809,
"3/16/20": 2158,
"3/17/20": 2503,
"3/18/20": 2978,
"3/19/20": 3405,
"3/20/20": 4032,
"3/21/20": 4825,
"3/22/20": 5476,
"3/23/20": 6077,
"3/24/20": 6820,
"3/25/20": 7503,
"3/26/20": 8215,
"3/27/20": 9134
}
}
}
As you can, I have dates for the month of February and March in this response. I want to get only the range of dates with the corresponding value within the current month, that is March in this case. How can I achieve this in jQuery?
$.ajax({
url: 'https://corona.lmao.ninja/v2/historical/italy',
type: 'GET',
dataType: 'JSON',
success: function(data) {
console.log('in');
console.log(data);
}
});
You may use Object.keys(), filter() & reduce() methods to acheive this like:
$.ajax({
url: 'https://corona.lmao.ninja/v2/historical/italy',
type: 'GET',
dataType: 'JSON',
success: function(data) {
const date = new Date(),y = date.getFullYear(),m = date.getMonth();
const firstDay = new Date(y, m, 1).getTime(), lastDay = new Date(y, m + 1, 0).getTime();
const currentData = Object.keys(data.timeline.cases)
.filter(key => firstDay <= new Date(key).getTime() && new Date(key).getTime() <= lastDay)
.reduce((o, k) => { o[k] = data.timeline.cases[k]; return o }, {});
console.log(currentData)
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
Explanation:
First inside ajax success method, we are trying to get first & last day of the current month, as we need those values to filter data.
Then using Object.keys we get all the keys in data.timeline.cases as this holds all the date strings as key.
Then using filter() method we get only the keys which are between first and last day of the current month.
Then using reduce() method we are trying to reconstruct the data.timeline.cases object back, so that you can use it in your application.
To achieve this you can use $.each() to determine whether the key in the cases object is a date within the current month and use it to create a new object with those entities. Try this:
$.ajax({
url: 'https://corona.lmao.ninja/v2/historical/italy',
type: 'GET',
dataType: 'JSON',
success: function(data) {
var currentMonth = new Date().getMonth();
var currentMonthCases = {};
$.each(data.timeline.cases, (k, v) => {
if (new Date(k).getMonth() === currentMonth)
currentMonthCases[k] = v;
})
console.log(currentMonthCases);
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
Using map, reduce, you can do is very easly. I have written a parser, will give you more stats. Please check.
const data = {
country: "italy",
timeline: {
cases: {
"1/22/20": 0,
"1/23/20": 0,
"1/24/20": 0,
"1/25/20": 0,
"1/26/20": 0,
"1/27/20": 0,
"1/28/20": 0,
"1/29/20": 0,
"1/30/20": 0,
"1/31/20": 2,
"2/1/20": 2,
"2/2/20": 2,
"2/3/20": 2,
"2/4/20": 2,
"2/5/20": 2,
"2/6/20": 2,
"2/7/20": 3,
"2/8/20": 3,
"2/9/20": 3,
"2/10/20": 3,
"2/11/20": 3,
"2/12/20": 3,
"2/13/20": 3,
"2/14/20": 3,
"2/15/20": 3,
"2/16/20": 3,
"2/17/20": 3,
"2/18/20": 3,
"2/19/20": 3,
"2/20/20": 3,
"2/21/20": 20,
"2/22/20": 62,
"2/23/20": 155,
"2/24/20": 229,
"2/25/20": 322,
"2/26/20": 453,
"2/27/20": 655,
"2/28/20": 888,
"2/29/20": 1128,
"3/1/20": 1694,
"3/2/20": 2036,
"3/3/20": 2502,
"3/4/20": 3089,
"3/5/20": 3858,
"3/6/20": 4636,
"3/7/20": 5883,
"3/8/20": 7375,
"3/9/20": 9172,
"3/10/20": 10149,
"3/11/20": 12462,
"3/12/20": 12462,
"3/13/20": 17660,
"3/14/20": 21157,
"3/15/20": 24747,
"3/16/20": 27980,
"3/17/20": 31506,
"3/18/20": 35713,
"3/19/20": 41035,
"3/20/20": 47021,
"3/21/20": 53578,
"3/22/20": 59138,
"3/23/20": 63927,
"3/24/20": 69176,
"3/25/20": 74386,
"3/26/20": 80589,
"3/27/20": 86498
},
deaths: {
"1/22/20": 0,
"1/23/20": 0,
"1/24/20": 0,
"1/25/20": 0,
"1/26/20": 0,
"1/27/20": 0,
"1/28/20": 0,
"1/29/20": 0,
"1/30/20": 0,
"1/31/20": 0,
"2/1/20": 0,
"2/2/20": 0,
"2/3/20": 0,
"2/4/20": 0,
"2/5/20": 0,
"2/6/20": 0,
"2/7/20": 0,
"2/8/20": 0,
"2/9/20": 0,
"2/10/20": 0,
"2/11/20": 0,
"2/12/20": 0,
"2/13/20": 0,
"2/14/20": 0,
"2/15/20": 0,
"2/16/20": 0,
"2/17/20": 0,
"2/18/20": 0,
"2/19/20": 0,
"2/20/20": 0,
"2/21/20": 1,
"2/22/20": 2,
"2/23/20": 3,
"2/24/20": 7,
"2/25/20": 10,
"2/26/20": 12,
"2/27/20": 17,
"2/28/20": 21,
"2/29/20": 29,
"3/1/20": 34,
"3/2/20": 52,
"3/3/20": 79,
"3/4/20": 107,
"3/5/20": 148,
"3/6/20": 197,
"3/7/20": 233,
"3/8/20": 366,
"3/9/20": 463,
"3/10/20": 631,
"3/11/20": 827,
"3/12/20": 827,
"3/13/20": 1266,
"3/14/20": 1441,
"3/15/20": 1809,
"3/16/20": 2158,
"3/17/20": 2503,
"3/18/20": 2978,
"3/19/20": 3405,
"3/20/20": 4032,
"3/21/20": 4825,
"3/22/20": 5476,
"3/23/20": 6077,
"3/24/20": 6820,
"3/25/20": 7503,
"3/26/20": 8215,
"3/27/20": 9134
}
}
};
const parseDate = srt => {
const [m, d, y] = srt.split("/");
return new Date(d, m - 1, y).getMonth();
};
const toArray = obj => {
const generator = function*() {
for (let key in obj) {
yield [obj[key], key];
}
};
return {
[Symbol.iterator]: generator,
map: function(fn) {
let result = [];
for (let [value, key] of this) {
result.push(fn(value, key));
}
return result;
}
};
};
const grouped = toArray(data.timeline.cases)
.map((x, k) => [x, k])
.reduce((m, c) => {
const parsedDate = parseDate(c[1]);
if (!m[parsedDate]) {
m[parsedDate] = { cases: [], deaths: [], totalCases: 0, totalDeaths: 0 };
}
m[parsedDate].cases.push({ date: c[1], cases: c[0] });
m[parsedDate].deaths.push({
date: c[1],
deaths: data.timeline.deaths[c[1]]
});
m[parsedDate].totalCases += c[0];
m[parsedDate].totalDeaths += data.timeline.deaths[c[1]];
return m;
}, {});
// console.log(JSON.stringify(grouped, null, 2));
// For march
console.log(JSON.stringify(grouped[2], null, 2));
console.log(grouped[2].totalDeaths);
console.log(grouped[2].totalCases);
// For feb
console.log(JSON.stringify(grouped[1], null, 2));
console.log(grouped[1].totalDeaths);
console.log(grouped[1].totalCases);
I have a working solution of this problem but I'm trying to make a cleaner and neat version of it as much as possible. I came up with another solution that uses a function within a map function. Unfortunately, this version has a few issues and I want to just know why the second solution is not working. I'm guessing it's a variable scope issue here. I'm looking forward to know your opinion about it.
I have a simple function that prints calendar days in an array!
So a question is why the first version of my code get the expected results while the second version prints unexpected results.
I tried to change let to var and I also made the counter and startedIndexing outside the function scope.
Solution 1 (works):
const currentFullMonth = {
days_length: 31,
first_day: "Thu",
first_day_index: 4,
last_day: "Sat",
last_day_index: 6,
month: "Aug",
year: 2019
}
const testMonth = [
[0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0]
];
function printMonthCalender(month) {
let counter = 0;
let startedIdxing = false;
return month.map(week => {
return week.map((day, index) => {
if (index === currentFullMonth.first_day_index && !startedIdxing) {
counter++;
startedIdxing = true;
return counter;
} else if (startedIdxing) {
if (currentFullMonth.days_length === counter) {
counter = 0;
}
counter++;
return counter;
} else {
return 0;
}
});
});
} // end of Solution #1 <-- this works :)
Solution 2 (doesn't work):
// start of Solution #2 <-- does not work :(
// im using two functions to make it look more cleaner
//
function printMonthCalender2(month) {
let counter = 0;
let startedIdxing = false;
return month.map(week => {
return week.map((day, index) =>
indexingMonth(counter, startedIdxing, index)
);
});
}
function indexingMonth(counter, startedIdxing, index) {
if (index === currentFullMonth.first_day_index && !startedIdxing) {
counter++;
startedIdxing = true;
return counter;
} else if (startedIdxing) {
if (currentFullMonth.days_length === counter) {
counter = 0;
}
counter++;
return counter;
} else {
return 0;
}
}// end of Solution #2
console.log(printMonthCalender(testMonth));
console.log(printMonthCalender2(testMonth));
expected result as follows (first version):
[0, 0, 0, 0, 1, 2, 3]
[4, 5, 6, 7, 8, 9, 10]
[11, 12, 13, 14, 15, 16, 17]
[18, 19, 20, 21, 22, 23, 24]
[25, 26, 27, 28, 29, 30, 31]
[1, 2, 3, 4, 5, 6, 7]
unexpected result as follows (second version):
[0, 0, 0, 0, 1, 0, 0]
[0, 0, 0, 0, 1, 0, 0]
[0, 0, 0, 0, 1, 0, 0]
[0, 0, 0, 0, 1, 0, 0]
[0, 0, 0, 0, 1, 0, 0]
[0, 0, 0, 0, 1, 0, 0]
The problem is that when you reassign startedIdxing inside of indexingMonth, it's a local variable, so it doesn't get changed inside of the calling function (printMonthCalender2).
An issue is that .map should not have mutation or reassignment as a side-effect. While you could tweak things so that indexingMonth returned something that you checked and then reassigned startedIdxing to, I'd prefer a different approach: create a flat array, eg
[0, 0, 0, 0, 1, 2, ..., 30, 31, 1, 2, 3]
and then chunk it into pieces of 7 afterwards:
const currentFullMonth = {
days_length: 31,
first_day: "Thu",
first_day_index: 4,
last_day: "Sat",
last_day_index: 6,
month: "Aug",
year: 2019
}
const makeZeroArr = length => new Array(length).fill(0);
const printMonthCalendar = (testMonth) => {
// Create array: [1, 2, 3, ..., 30, 31]
const oneMonth = Array.from(
{ length: currentFullMonth.days_length },
(_, i) => i + 1
);
// Create a flat array with leading zeros and trailing last week:
// [0, 0, 0, 0, 1, 2, 3, ..., 30, 31, 1, 2, 3, 4, 5, 6, 7]
const flatResultArr = [
...makeZeroArr(currentFullMonth.first_day_index),
...oneMonth,
...oneMonth // this includes extra numbers that will be trimmed
].slice(0, 7 * 6); // 7 days/week * 6 weeks
// Chunk the flat array into slices of 7:
const resultArr = [];
for (let i = 0; i < 7; i++) {
resultArr.push(flatResultArr.slice(i * 7, (i + 1) * 7));
}
return resultArr;
};
console.log(printMonthCalendar());
In functions, primitive types like numbers and booleans are passed by value, not by reference. So when you define counter and startedIdxing in printMonthCalender2 and then try to change them in indexingMonth, the changes get lost as soon as you return to printMonthCalender2.
However in JavaScript, objects get passed by reference. So something like this would work:
function printMonthCalender2(month) {
let obj = { counter: 0, startedIdxing = false };
return month.map(week => {
return week.map((day, index) =>
indexingMonth(obj, index)
);
});
}
function indexingMonth(obj, index) {
if (index === currentFullMonth.first_day_index && !obj.startedIdxing) {
obj.counter++;
obj.startedIdxing = true;
return obj.counter;
} else if (obj.startedIdxing) {
if (currentFullMonth.days_length === obj.counter) {
obj.counter = 0;
}
obj.counter++;
return obj.counter;
} else {
return 0;
}
}// end of Solution #2
Things like obj.counter++ will actually keep those changes in your original object defined in printMonthCalender2.
Warning: While you can do this, if you are working with complex code this is often frowned upon. These kinds of mutations can be very difficult to debug if a problem occurs. It's a legitimate programming technique, but shouldn't be abused.
Also if you're working in a team that adheres to the functional programming paradigm, I believe this is a big no-no.
However given the very short duration and limited scope of the obj variable in this example, I would personally feel very comfortable with this. If obj had a much longer lifetime and was used in numerous places in the code then I'd be more wary of it, and would agree with #CertainPerformance's comment that a map statement shouldn't mutate things.
i have this following Array :
var objRow = [
{
2011-09-20 : [0, 100, 0],
customerID : C1101,
ANI : 1234
},
{
2011-09-25 : [0, 0, 0],
customerID : C1101,
ANI : 1234
},
{
2011-09-20 : [0, 500, 0],
customerID : C1102,
ANI : 5678
},
{
2011-09-22 : [0, 0, 50],
customerID : C1102,
ANI : 5678
}
]
I want to create CSV Data from array above. But, i have problem to change that array to this CSV pattern :
1234, C1101, 0, 0, 100, 0, 0, 0
5678, C1102, 0, 0, 500, 0, 0, 50
I try to group the customerID using reduce, and because the first index in every object is date. I have some array of dates :
var dateArr = ["2011-09-20", "2011-09-22", "2011-09-25"];
And this is my code :
var result = objRow.reduce(function(prev, curr, index, arr) {
var num = curr["customerID"];
if (!prev[num]) {
prev[num] = [];
}
for (var j = 0; j < dateArr.length; j++) {
prev[num].push(curr[dateArr[j]]);
}
return prev;
}, {});
Update Question
For number combination in date index. I use this rules :
[0, 100, 0] // from first Object
[0, 0, 0] // from second Object
fistObject_firstIndex, secondObject_firstIndex, firstObject_secondIndex, secondObject_secondIndex, firstObject_thirdIndex, secondObject_thirdIndex
0, 0, 100, 0, 0, 0
Up, Down, Up, Down, Up, Down...
How to create CSV Pattern above?
Thank you...
I think this will give you the result you want:
var objRow = [{
date: 2011-09-20,
nums: [0, 100, 0],
customerID: "C1101",
ANI: 1234
}, {
date: 2011-09-25,
nums: [0, 0, 0],
customerID: "C1101",
ANI: 1234
}, {
date: 2011-09-20,
nums: [0, 500, 0],
customerID: "C1102",
ANI: 5678
}, {
date: 2011-09-22,
nums: [0, 0, 50],
customerID: "C1102",
ANI: 5678
}];
//CREATE CSV-FORMATTED STRINGS
var csvLine = "";
var numsArray = new Array();
for (var i=0; i<objRow.length; i++) {
//check if this is the first element with a new 'ANI' (which means a new CSV line starts)
if (objRow[i-1]==(undefined||null) || objRow[i].ANI!=objRow[i-1].ANI) {
//if so, start a new string
csvLine = objRow[i].ANI +", "+ objRow[i].customerID +", "; //add the 'ANI' and 'customerID'
numsArray.length = 0; //clear array
numsArray.push(objRow[i].nums); //store the 'nums' in a separate array
} else {
//if not, add to the existing string
numsArray.push(objRow[i].nums); //store the 'nums' in a separate array
}
//check if this is the last element with the same 'ANI' (which means this CSV line is complete)
if (objRow[i+1]==(undefined||null) || objRow[i].ANI!=objRow[i+1].ANI) {
//add the 'nums' of every object in intertwining order (every 1st, every 2nd, etc.)
for (var k=0; k<numsArray[0].length; k++) {
for (var j=0; j<numsArray.length; j++) {
csvLine += numsArray[j][k].toString() +", ";
}
}
//remove the last comma
if (csvLine.substring(csvLine.length-2) == ", ") {
csvLine = csvLine.substring(0,csvLine.length-2);
}
//output the CSV line
document.getElementById("csv").innerHTML += csvLine + "<br />";
}
}
<div id="csv"></div>
(fiddle: http://jsfiddle.net/5gyp3ce6/16/)
I had to change your array a little bit, because for this to work, the array keys need to all be the same.
Also, I had to change the ID's to strings, otherwise they couldn't be defined.
Instead of writing it to the <div> at the end you can of course add the line to another variable of write it to file or whatever.
If the comments in the code aren't clear enough, just leave a comment and I'll try to explain it better.
Try
var objRow = [
{
"2011-09-20" : [0, 100, 0],
customerID : "C1101",
ANI : 1234
},
{
"2011-09-25" : [0, 0, 0],
customerID : "C1101",
ANI : 1234
},
{
"2011-09-20" : [0, 500, 0],
customerID : "C1102",
ANI : 5678
},
{
"2011-09-22" : [0, 0, 50],
customerID : "C1102",
ANI : 5678
}
];
var arr = [],
res = [],
csv = $.map(objRow, function (v, k) {
// items
arr.push(v.ANI, v.customerID, v[Object.keys(v)[0]]);
// arrays
var a = $.grep(arr, function (val, index) {
return $.isArray(val)
});
// strings
var s = arr.filter(function (i) {
return typeof i === "string"
});
// sort items
res.push([arr.filter(Number)[0]
, s[0]
, a.splice(0, 2).join(",")
, arr.filter(Number).slice(-1)[0]
, s.slice(-1)[0]
, a.join(",")]);
return res
}).slice(-1)[0];
// format text , html
csv = (csv.slice(0, 3) + "<br>" + csv.slice(-3))
.replace(/,/g, ", ");
$("body").append(csv)
var objRow = [
{
"2011-09-20" : [0, 100, 0],
customerID : "C1101",
ANI : 1234
},
{
"2011-09-25" : [0, 0, 0],
customerID : "C1101",
ANI : 1234
},
{
"2011-09-20" : [0, 500, 0],
customerID : "C1102",
ANI : 5678
},
{
"2011-09-22" : [0, 0, 50],
customerID : "C1102",
ANI : 5678
}
];
var arr = [],
res = [],
csv = $.map(objRow, function (v, k) {
arr.push(v.ANI, v.customerID, v[Object.keys(v)[0]]);
// arrays
var a = $.grep(arr, function (val, index) {
return $.isArray(val)
});
// strings
var s = arr.filter(function (i) {
return typeof i === "string"
});
res.push([arr.filter(Number)[0], s[0], a.splice(0, 2).join(","), arr.filter(Number).slice(-1)[0], s.slice(-1)[0], a.join(",")]);
return res
}).slice(-1)[0];
csv = (csv.slice(0, 3) + "<br>" + csv.slice(-3))
.replace(/,/g, ", ");
$("body").append(csv)
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>